home *** CD-ROM | disk | FTP | other *** search
Wrap
Text File | 2000-02-17 | 730.3 KB | 22,340 lines
/*------------------------------------------------------------------------------ sp2_repl.sql THIS SCRIPT UPDATES REPLICATION SYSTEM STORED PROCEDURES FROM 7.0 SP1 and SP2. Changes in this file are organized as follows (please maintain): Common system objects (replsys.sql) Common repl objects (replcom.sql) Tran repl objects (repltran.sql) Merge repl objects (rladmin.sql, rlrecon.sql, rlcore.sql) Notes: + Catalog-updates and sp_MS_upd_sysobj_category are enabled for the entire file. Do not disable or re-enable them. Please do not change set options. + grep for "--. ------------------------------------------------------------------------------*/ -------------------------------------------------------------------------------- -- VERIFY Server is started in single-user-mode (catalog-updates enabled), and -- start marking of system-objects. -------------------------------------------------------------------------------- use master go dump tran master with no_log go exec dbo.sp_configure 'allow updates',1 go reconfigure with override go set ANSI_NULLS off exec sp_MS_upd_sysobj_category 1 go -------------------------------------------------------------------------------- --. Common system objects (replsys.sql) -------------------------------------------------------------------------------- -------------------------------------------------------------------------------- --. Update MSreplication_options indexes -------------------------------------------------------------------------------- raiserror('Creating ucMSreplication_options if needed', 0,1) GO IF NOT EXISTS ( SELECT * FROM sysindexes where name = 'ucMSreplication_options' and id = OBJECT_ID('MSreplication_options')) CREATE UNIQUE CLUSTERED INDEX ucMSreplication_options ON MSreplication_options(optname) GO -------------------------------------------------------------------------------- --. Drop sp_vupgrade_MSsubscription_properties - no longer used -------------------------------------------------------------------------------- raiserror('Dropping procedure sp_vupgrade_MSsubscription_properties if needed', 0,1) GO if exists (select * from sysobjects where type = 'P' and name = 'sp_vupgrade_MSsubscription_properties') drop procedure sp_vupgrade_MSsubscription_properties go -------------------------------------------------------------------------------- --. Drop sp_vupgrade_publisher - no longer used -------------------------------------------------------------------------------- raiserror('Dropping procedure sp_vupgrade_publisher if needed', 0,1) GO if exists (select * from sysobjects where type = 'P' and name = 'sp_vupgrade_publisher') drop procedure sp_vupgrade_publisher go -------------------------------------------------------------------------------- --. Drop sp_vupgrade_publisherdb - no longer used -------------------------------------------------------------------------------- raiserror('Dropping procedure sp_vupgrade_publisherdb if needed', 0,1) GO if exists (select * from sysobjects where type = 'P' and name = 'sp_vupgrade_publisherdb') drop procedure sp_vupgrade_publisherdb go -------------------------------------------------------------------------------- --. sp_MSreplcheck_name -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSreplcheck_name') drop procedure sp_MSreplcheck_name go raiserror('Creating procedure sp_MSreplcheck_name', 0,1) GO CREATE PROCEDURE sp_MSreplcheck_name @name sysname, @raise_error bit = 1 AS declare @index int Set nocount on -- Name cannot be NULL or empty ("") -- Blank identifiers (" ") are allowed IF (@name is null OR datalength(@name) = 0) begin if @raise_error = 1 raiserror (15004,16,-1) return (1) end -- Check for proscribed characters declare @length int select @length = datalength( @name ) / 2 select @index = 1 while @index < @length begin if( 0 = unicode( substring( @name, @index, 1 ) ) ) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = @index + 1 end --check for other proscribed characters select @index = charindex( N'%', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N'*', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N'[', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N']', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N'|', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N':', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N'"', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N'?', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end /* ** Fix 52855 - allow single quote ** select @index = charindex(N'''', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end */ select @index = charindex(N'\', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N'/', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N'<', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end select @index = charindex(N'>', @name) if (@index <> 0) begin if @raise_error = 1 raiserror(15006,16,-1,@name) return (1) end -- return success return (0) GO -------------------------------------------------------------------------------- --. sp_MScreate_mergesystables -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MScreate_mergesystables') drop procedure sp_MScreate_mergesystables go raiserror('Creating procedure sp_MScreate_mergesystables',0,1) GO create procedure sp_MScreate_mergesystables as /* This is to make sure that the varbinary columns do not get padded */ set ANSI_PADDING off DECLARE @exist bit DECLARE @validsubs int select @exist = 1 begin tran save transaction MScreate_mergesystables exec dbo.sp_MScheckvalidsystables @validsubs output if @validsubs = 0 exec dbo.sp_MSdrop_mergesystables if not exists (select * from sysobjects where name = 'sysmergepublications') begin raiserror('Creating table sysmergepublications',0,1) create table dbo.sysmergepublications ( publisher sysname NOT NULL default @@servername, publisher_db sysname NOT NULL default db_name(), name sysname NOT NULL, description nvarchar(255) NULL, retention int NULL, publication_type tinyint NULL, pubid uniqueidentifier NOT NULL, designmasterid uniqueidentifier NULL, parentid uniqueidentifier NULL, sync_mode tinyint NULL, allow_push int NULL, allow_pull int NULL, allow_anonymous int NULL, centralized_conflicts int NULL, status tinyint NULL, snapshot_ready tinyint NULL, enabled_for_internet bit NOT NULL default 0, dynamic_filters bit NOT NULL default 0, keep_before_values int NULL default 0 ) if @@ERROR <> 0 goto Error else begin create unique nonclustered index nc1sysmergepublications on sysmergepublications(pubid) if @@ERROR <> 0 goto Error end exec dbo.sp_MS_marksystemobject sysmergepublications if @@ERROR <> 0 goto Error grant select on sysmergepublications to public end if not exists (select * from sysobjects where name = 'sysmergearticles') begin raiserror('Creating table sysmergearticles',0,1) create table dbo.sysmergearticles ( name sysname NOT NULL, type tinyint NULL, objid int NOT NULL, sync_objid int NOT NULL, view_type tinyint NULL, artid uniqueidentifier NOT NULL, description nvarchar(255) NULL, pre_creation_command tinyint NULL, pubid uniqueidentifier NOT NULL, nickname int NOT NULL, column_tracking int NOT NULL, status tinyint NULL, conflict_table sysname NULL, creation_script nvarchar(255) NULL, conflict_script nvarchar(255) NULL, article_resolver nvarchar(255) NULL, ins_conflict_proc sysname NULL, insert_proc sysname NULL, update_proc sysname NULL, select_proc sysname NULL, schema_option binary(8) NULL, destination_object sysname NOT NULL, resolver_clsid nvarchar(50) NULL, subset_filterclause nvarchar(1000) NULL, missing_col_count int NULL, missing_cols varbinary(128) NULL, columns varbinary(128) NULL, resolver_info nvarchar(255) NULL, view_sel_proc nvarchar(290) NULL, gen_cur int NULL, before_image_objid int NULL, before_view_objid int NULL ) if @@error<>0 goto Error else begin create unique clustered index uc1sysmergearticles on sysmergearticles(artid, pubid) if @@ERROR <> 0 goto Error end exec dbo.sp_MS_marksystemobject sysmergearticles if @@ERROR <> 0 goto Error grant select on sysmergearticles to public end if not exists (select * from sysobjects where name = 'sysmergesubscriptions') begin raiserror('Creating table sysmergesubscriptions',0,1) create table dbo.sysmergesubscriptions ( subid uniqueidentifier NOT NULL, partnerid uniqueidentifier NOT NULL, datasource_type int NOT NULL, datasource_path nvarchar(255) NULL, srvid int NOT NULL, db_name sysname NOT NULL constraint unique_pubsrvdb unique nonclustered (pubid, srvid, db_name), pubid uniqueidentifier NULL, status tinyint NOT NULL, subscriber_type int NOT NULL, subscription_type int NOT NULL, priority real NOT NULL, sync_type tinyint NOT NULL, -- 1 = automatic 2 = no sync description nvarchar(255) NULL, login_name sysname NOT NULL, last_validated datetime NULL ) if @@error<>0 goto Error else begin create unique clustered index uc1sysmergesubscriptions on sysmergesubscriptions (subid) if @@ERROR<>0 goto Error end exec dbo.sp_MS_marksystemobject sysmergesubscriptions if @@ERROR <> 0 goto Error grant select on sysmergesubscriptions to public end if not exists (select * from sysobjects where name = 'MSmerge_replinfo') begin raiserror('Creating table MSmerge_replinfo',0,1) create table dbo.MSmerge_replinfo ( repid uniqueidentifier NOT NULL, replnickname int NOT NULL, recgen int NULL, recguid uniqueidentifier NULL, sentgen int NULL, sentguid uniqueidentifier NULL, schemaversion int NULL, schemaguid uniqueidentifier NULL, merge_jobid binary(16) NULL, snapshot_jobid binary(16) NULL ) if @@ERROR <> 0 goto Error else begin create unique clustered index uc1MSmerge_replinfo on MSmerge_replinfo (repid) if @@ERROR <> 0 goto Error end exec dbo.sp_MS_marksystemobject MSmerge_replinfo if @@ERROR <> 0 goto Error grant select on MSmerge_replinfo to public end if not exists (select * from sysobjects where name = 'MSmerge_tombstone') begin raiserror('Creating table MSmerge_tombstone',0,1) create table dbo.MSmerge_tombstone ( rowguid uniqueidentifier rowguidcol NOT NULL, tablenick int NOT NULL, type tinyint NOT NULL, lineage varbinary(255) NOT NULL, generation int NOT NULL, reason nvarchar(255) NOT NULL, ) if @@ERROR <> 0 goto Error else begin create unique clustered index uc1MSmerge_tombstone on MSmerge_tombstone (tablenick, rowguid) if @@ERROR <> 0 goto Error create index nc2MSmerge_tombstone on MSmerge_tombstone (generation) if @@ERROR <> 0 goto Error end exec dbo.sp_MS_marksystemobject MSmerge_tombstone if @@ERROR <> 0 goto Error grant select on MSmerge_tombstone to public end if not exists (select * from sysobjects where name = 'MSmerge_contents') begin raiserror('Creating table MSmerge_contents',0,1) create table dbo.MSmerge_contents ( tablenick int NOT NULL, rowguid uniqueidentifier rowguidcol NOT NULL, generation int NOT NULL, partchangegen int NULL, joinchangegen int NULL, lineage varbinary(249) NOT NULL, colv1 varbinary(2048) NULL, ) if @@ERROR <> 0 goto Error else begin create unique clustered index uc1SycContents on MSmerge_contents( tablenick, rowguid ) if @@ERROR <> 0 goto Error create index nc2MSmerge_contents on MSmerge_contents(tablenick, generation) if @@ERROR <> 0 goto Error create index nc3MSmerge_contents on MSmerge_contents(tablenick, partchangegen) if @@ERROR <> 0 goto Error create index nc4MSmerge_contents on MSmerge_contents(generation, partchangegen) if @@ERROR <> 0 goto Error end exec dbo.sp_MS_marksystemobject MSmerge_contents if @@ERROR <> 0 goto Error grant select on MSmerge_contents to public end if not exists (select * from sysobjects where name = 'MSmerge_genhistory') begin raiserror('Creating table MSmerge_genhistory',0,1) create table dbo.MSmerge_genhistory ( guidsrc uniqueidentifier NOT NULL, guidlocal uniqueidentifier NOT NULL, pubid uniqueidentifier NULL, generation int NOT NULL, art_nick int NULL, nicknames varbinary(255) NOT NULL, coldate datetime NOT NULL ) if @@ERROR <> 0 goto Error create clustered index uc1MSmerge_genhistory on MSmerge_genhistory(guidsrc) if @@ERROR <> 0 goto Error create index nc1MSmerge_genhistory on MSmerge_genhistory(generation) if @@ERROR <> 0 goto Error create index nc2MSmerge_genhistory on MSmerge_genhistory(guidlocal) if @@ERROR <> 0 goto Error create unique index nc3MSmerge_genhistory on MSmerge_genhistory(guidsrc, pubid) if @@ERROR <> 0 goto Error create index nc4MSmerge_genhistory on MSmerge_genhistory(coldate) if @@ERROR <> 0 goto Error exec dbo.sp_MS_marksystemobject MSmerge_genhistory if @@ERROR <> 0 goto Error grant select on MSmerge_genhistory to public end if not exists (select * from sysobjects where name = 'MSmerge_delete_conflicts') begin raiserror('Creating table MSmerge_delete_conflicts',0,1) create table dbo.MSmerge_delete_conflicts ( tablenick int NOT NULL, rowguid uniqueidentifier rowguidcol NOT NULL, origin_datasource nvarchar(255) NULL, conflict_type int NULL, reason_code int NULL, reason_text nvarchar(720) NULL, pubid uniqueidentifier NULL ) if @@ERROR <> 0 goto Error else begin create clustered index uc1MSmerge_delete_conflicts on MSmerge_delete_conflicts(tablenick, rowguid) if @@ERROR <> 0 goto Error end create unique index nc1MSmerge_delete_conflicts on MSmerge_delete_conflicts(tablenick, rowguid, origin_datasource) if @@ERROR <> 0 goto Error exec dbo.sp_MS_marksystemobject MSmerge_delete_conflicts if @@ERROR <> 0 goto Error grant select on MSmerge_delete_conflicts to public end if not exists (select * from sysobjects where name = 'sysmergeschemachange') begin raiserror('Creating table sysmergeschemachange',0,1) create table dbo.sysmergeschemachange ( pubid uniqueidentifier NOT NULL, artid uniqueidentifier NULL, schemaversion int NOT NULL, schemaguid uniqueidentifier NOT NULL, schematype int NOT NULL, schematext nvarchar(2000) NOT NULL ) if @@ERROR <> 0 goto Error else begin create unique clustered index schemachangeversion on sysmergeschemachange(schemaversion, pubid) if @@ERROR <> 0 goto Error end exec dbo.sp_MS_marksystemobject sysmergeschemachange if @@ERROR <> 0 goto Error grant select on sysmergeschemachange to public end if not exists (select * from sysobjects where name = 'sysmergesubsetfilters') begin raiserror('Creating table sysmergesubsetfilters',0,1) create table dbo.sysmergesubsetfilters ( filtername sysname NOT NULL, join_filterid int identity NOT NULL, pubid uniqueidentifier NOT NULL, artid uniqueidentifier NOT NULL, art_nickname int NOT NULL, join_articlename sysname NOT NULL, join_nickname int NOT NULL, join_unique_key int NOT NULL, expand_proc sysname NULL, join_filterclause nvarchar(1000) NULL ) if @@ERROR <> 0 goto Error else begin create unique index nc1sysmergesubsetfilters on sysmergesubsetfilters(join_filterid, pubid) if @@ERROR <> 0 goto Error end exec dbo.sp_MS_marksystemobject sysmergesubsetfilters if @@ERROR <> 0 goto Error grant select on sysmergesubsetfilters to public end if @@error <> 0 return(1) commit transaction return (0) Error: if @@trancount > 0 begin ROLLBACK TRANSACTION MScreate_mergesystables COMMIT TRANSACTION end RAISERROR (20008, 16, -1) return (1) go -------------------------------------------------------------------------------- --. Update permissions for sp_MStestbit -------------------------------------------------------------------------------- raiserror('Granting execution on sp_MStestbit to public', 0,1) go grant exec on dbo.sp_MStestbit to public go -------------------------------------------------------------------------------- --. Update permissions for sp_MSsetbit -------------------------------------------------------------------------------- raiserror('Granting execution on sp_MSsetbit to public', 0,1) go grant exec on dbo.sp_MSsetbit to public go -------------------------------------------------------------------------------- --. sp_MSunmarkifneeded -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSunmarkifneeded') drop procedure sp_MSunmarkifneeded go raiserror('Creating procedure sp_MSunmarkifneeded',0,1) GO CREATE PROCEDURE sp_MSunmarkifneeded( @object sysname, @pubid uniqueidentifier, @pre_command int = 1, @publisher sysname = NULL, @publisher_db sysname = NULL )AS declare @table_in_use int declare @retcode int select @table_in_use = 0 --if pre-creation_command is 'drop (1)' or 'truncate (3)', then disallow this deployment if there is already an article using that table. --other commands, 'delete', and 'none' are fine', as long as the publication does not originate from same database. if exists (select * from sysmergearticles where objid=object_id(@object) and pubid in (select pubid from sysmergepublications where LOWER(publisher)=LOWER(@publisher) and publisher_db=@publisher_db and pubid<>@pubid)) OR ((@pre_command=1 or @pre_command=3) and EXISTS (select * from sysmergearticles where objid=object_id(@object) and pubid <> @pubid)) begin select @table_in_use = 1 select @table_in_use return (0) end exec @retcode = sp_MSunmarkreplinfo @object if @retcode <>0 or @@error<>0 return (1) select @table_in_use return (0) GO grant exec on dbo.sp_MSunmarkifneeded to public go -------------------------------------------------------------------------------- --. sp_reinitmergepullsubscription -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_reinitmergepullsubscription') drop procedure sp_reinitmergepullsubscription go raiserror('Creating procedure sp_reinitmergepullsubscription', 0, 1) GO create procedure sp_reinitmergepullsubscription @publisher sysname = 'all', @publisher_db sysname = 'all', @publication sysname = 'all' AS declare @schemaversion int declare @schematype smallint declare @retcode int declare @schemaguid uniqueidentifier declare @pubname sysname declare @publisher_name sysname declare @pubdb sysname declare @pubid uniqueidentifier declare @subid uniqueidentifier declare @artid uniqueidentifier /* ** Replace 'all' with '%' */ if LOWER(@publication) = 'all' SELECT @publication = '%' if LOWER(@publisher) = 'all' SELECT @publisher = '%' if LOWER(@publisher_db) = 'all' SELECT @publisher_db = '%' /* ** At subscriber side, we need to qualify the publication with server name and database name */ IF NOT EXISTS (SELECT * FROM sysmergepublications WHERE name LIKE @publication and ((@publisher = N'%') or (UPPER(publisher) = UPPER(@publisher))) and publisher_db like @publisher_db) BEGIN IF @publication = '%' RAISERROR (14008, 11, -1) ELSE RAISERROR (20026, 11, -1, @publication) RETURN (1) END Declare SYN_CUR CURSOR LOCAL FAST_FORWARD FOR select subs.subid, pubs.name, pubs.publisher, pubs.publisher_db from sysmergepublications pubs, sysmergesubscriptions subs where pubs.name LIKE @publication AND ((@publisher = '%') OR (UPPER(pubs.publisher) = UPPER(@publisher))) AND pubs.publisher_db LIKE @publisher_db AND pubs.pubid=subs.pubid AND subs.pubid<>subs.subid FOR READ ONLY open SYN_CUR fetch SYN_CUR into @subid, @pubname, @publisher_name, @pubdb while (@@fetch_status<>-1) BEGIN exec @retcode=sp_MSCleanupForPullReinit @publication=@pubname, @publisher=@publisher_name, @publisher_db=@pubdb if @retcode<>0 or @@ERROR<>0 return (1) update MSmerge_replinfo set schemaversion=-1, recgen = NULL, recguid=NULL, sentgen=NULL, sentguid = NULL where repid=@subid AND schemaversion is NOT NULL fetch next from SYN_CUR into @subid, @pubname, @publisher_name, @pubdb -- so that it won't be treated as a new susbscription END close SYN_CUR deallocate SYN_CUR -- Forget that publisher ever sent us any generations. They must be resent. -- Publication cleanup will remove the genhistory rows. if @publication = '%' -- get them all update MSmerge_replinfo set recgen = NULL, recguid=NULL, sentgen=NULL, sentguid = NULL else begin select @pubid = pubid from sysmergepublications where name = @publication update MSmerge_replinfo set recgen = NULL, recguid=NULL, sentgen=NULL, sentguid = NULL where repid in (select subid from sysmergesubscriptions where pubid = @pubid) end GO grant execute on dbo.sp_reinitmergepullsubscription to public go -------------------------------------------------------------------------------- --. sp_MSenumallpublications -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSenumallpublications') drop procedure sp_MSenumallpublications go raiserror('Creating procedure sp_MSenumallpublications', 0,1) go CREATE PROCEDURE sp_MSenumallpublications( @publisherdb sysname = '%', @replication_type tinyint = 1, @agent_login sysname = NULL, @security_check bit = 1 -- Security check by default so that things depending on security -- filtering will not break immediately ) as set nocount on declare @dbname sysname declare @trans tinyint declare @merge tinyint declare @3rdparty tinyint declare @retcode int DECLARE @dist_rpcname sysname declare @distribdb sysname declare @login sysname declare @proc nvarchar(255) declare @distbit int declare @is_user_admin bit declare @same_as_user bit -- UI: If the distributor is not installed, return empty result if not exists (SELECT * FROM master..sysservers WHERE srvstatus & 8 <> 0) return (0) -- UI: Win95 subscriber will send in null agent_login -- Assume the agent login to be the current login if it is NT login if @security_check = 1 and @agent_login is null and not exists (select * from master.dbo.syslogins where sid = suser_sid() and isntname = 0) select @agent_login = suser_sname(suser_sid()) /* Initializations */ select @trans = 1 select @merge = 2 select @3rdparty = 0 select @login = suser_sname(suser_sid()) SELECT @distbit = 16 select @is_user_admin = 0 select @same_as_user = 0 -- Get publication list create table #pubdbs (publisher_db sysname NOT NULL, replication_type int NOT NULL) /* Return everything if @replication_type is not in (@3rdparty, @trans, @merge) */ if not @replication_type in (@3rdparty, @trans, @merge) select @replication_type = null if @replication_type = @trans or @replication_type is null insert into #pubdbs select name, @trans from master..sysdatabases where name like @publisherdb and category & 1 <> 0 and (isnull(databaseproperty(name, N'issuspect'), 0) = 0 and isnull(databaseproperty(name, N'isshutdown'), 0) = 0) and has_dbaccess(name) = 1 if @replication_type = @merge or @replication_type is null insert into #pubdbs select name, @merge from master..sysdatabases where name like @publisherdb and category & 4 <> 0 and (isnull(databaseproperty(name, N'issuspect'), 0) = 0 and isnull(databaseproperty(name, N'isshutdown'), 0) = 0) and has_dbaccess(name) = 1 if @replication_type = @3rdparty insert into #pubdbs select name, @3rdparty from master..sysdatabases where name like @publisherdb and category & @distbit <> 0 and (isnull(databaseproperty(name, N'issuspect'), 0) = 0 and isnull(databaseproperty(name, N'isshutdown'), 0) = 0) and has_dbaccess(name) = 1 create table #MSenumpublications (publisher_db sysname NOT NULL, publication sysname NOT NULL, replication_type tinyint NOT NULL, immediate_sync bit NOT NULL, allow_pull bit NOT NULL, allow_anonymous bit NOT NULL, enabled_for_internet bit NOT NULL, repl_freq tinyint NOT NULL, immediate_sync_ready bit NOT NULL, allow_sync_tran bit NOT NULL, independent_agent bit NOT NULL, is_db_owner int NOT NULL, thirdparty_flag bit NOT NULL, vendor_name sysname NULL, publisher sysname NULL, description nvarchar(255) NULL, distribution_db sysname NULL) declare hCForEachDb CURSOR LOCAL FAST_FORWARD FOR select publisher_db, replication_type from #pubdbs FOR READ ONLY open hCForEachDb fetch hCForEachDb into @dbname, @replication_type /* Loop for each database */ while (@@fetch_status >= 0) begin if (@replication_type) = @trans select @proc = quotename(@dbname) + '.dbo.sp_MSenumtranpublications' else if (@replication_type) = @merge select @proc = quotename(@dbname) + '.dbo.sp_MSenummergepublications' else if (@replication_type) = @3rdparty select @proc = quotename(@dbname) + '.dbo.sp_MSenum3rdpartypublications' insert into #MSenumpublications exec @retcode = @proc if @@ERROR <> 0 or @retcode <> 0 return (1) fetch hCForEachDb into @dbname, @replication_type end /* while FETCH_SUCCESS */ -- Prepare for filtering. create table #admin_publications (publisher_db sysname not null, publication sysname not null) create table #agent_publications (publisher_db sysname not null, publication sysname not null) IF (@security_check <> 0) BEGIN EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @dist_rpcname OUTPUT, @distribdb = @distribdb OUTPUT IF @@error <> 0 OR @retcode <> 0 RETURN (1) IF @distribdb is null BEGIN RAISERROR (14071, 16, -1) RETURN (1) END SELECT @proc = RTRIM(@dist_rpcname) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSpublication_access' -- Optimization if is_srvrolemember('sysadmin') = 1 select @is_user_admin = 1 else insert into #admin_publications EXEC @retcode = @proc @publisher = @@SERVERNAME, @operation = 'get_publications', @login = @login if suser_sid(@agent_login) = suser_sid() select @same_as_user = 1 else insert into #agent_publications EXEC @retcode = @proc @publisher = @@SERVERNAME, @operation = 'get_publications', @login = @agent_login END -- IF (@security_check <> 0) -- workaround of a server bug of leaving tran open when -- insert into exec failed. while(@@trancount <> 0) commit tran DONE2: select pub.publisher_db, pub.publication, pub.replication_type, pub.immediate_sync, pub.allow_pull, pub.allow_anonymous, pub.enabled_for_internet, pub.repl_freq, pub.immediate_sync_ready, pub.allow_sync_tran, pub.independent_agent, N'agent_access' = case when (@same_as_user = 1 or exists (select * from #agent_publications agent where agent.publisher_db = pub.publisher_db and agent.publication = pub.publication)) then convert(bit,1) else convert(bit,0) end, pub.thirdparty_flag, pub.vendor_name, pub.publisher, pub.description, pub.distribution_db from #MSenumpublications pub where exists (select * from #admin_publications admin where pub.publisher_db = admin.publisher_db and pub.publication = admin.publication) or @security_check = 0 or pub.is_db_owner = 1 or @is_user_admin = 1 order by pub.publication, pub.publisher_db return (0) go grant execute on dbo.sp_MSenumallpublications to public go -------------------------------------------------------------------------------- --. sp_reinitpullsubscription -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_reinitpullsubscription') drop procedure sp_reinitpullsubscription go raiserror('Creating procedure sp_reinitpullsubscription', 0,1) go CREATE PROCEDURE sp_reinitpullsubscription ( @publisher sysname, @publisher_db sysname, @publication sysname = 'all' /* publication name */ )AS SET NOCOUNT ON declare @subscription_type int declare @sync_type tinyint /* ** Security Check */ declare @retcode int EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) /* ** Initializations. */ /* ** Parameter Check: @publisher ** Check to make sure that the publisher is define */ IF @publisher IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher') RETURN (1) END IF @publisher = 'all' BEGIN RAISERROR (14136, 16, -1) 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 IF @publisher_db = 'all' BEGIN RAISERROR (14136, 16, -1) RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publisher_db IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) /* ** Parameter Check: @publication ** */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END IF LOWER(@publication) = 'all' select @publication = '%' ELSE BEGIN EXECUTE @retcode = dbo.sp_validname @publication IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) END IF NOT EXISTS (SELECT * FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication like @publication ) BEGIN RAISERROR(14135, 11, -1, @publisher, @publisher_db, @publication) RETURN(1) END select @sync_type = immediate_sync from MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication like @publication IF @sync_type = 0 BEGIN raiserror(21059, 16, -1) return (1) END UPDATE MSreplication_subscriptions set transaction_timestamp = 0x00 WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication like @publication if @@ERROR<>0 RETURN (1) GO grant execute on dbo.sp_reinitpullsubscription to public go -------------------------------------------------------------------------------- --. sp_droppullsubscription -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_droppullsubscription') drop procedure sp_droppullsubscription go raiserror('Creating procedure sp_droppullsubscription', 0,1) go CREATE PROCEDURE sp_droppullsubscription ( @publisher sysname, @publisher_db sysname, @publication sysname, /* publication name */ @reserved bit = 0 ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @name nvarchar(255) DECLARE @retcode int DECLARE @agent_id binary(16) DECLARE @publisher_ex sysname /* Expression used in the cursor */ DECLARE @publisher_db_ex sysname /* Expression used in the cursor */ DECLARE @publication_ex sysname /* Expression used in the cursor */ DECLARE @expanded bit DECLARE @subscription_type_id int DECLARE @count_sub int DECLARE @drop_null_pub bit DECLARE @drop_push_bit bit DECLARE @push int DECLARE @implicit_transaction int DECLARE @close_cursor_at_commit int DECLARE @owner_sid varbinary(85) DECLARE @owner_name sysname DECLARE @qualified_publication_name nvarchar(512) /* ** Initialization */ SELECT @expanded = 0 SELECT @drop_null_pub = 0 SELECT @push = 0 /* ** Get the original set value off IMPLICIT_TRANSACTIONS and CURSOR_CLOSE_ON_COMMIT ** before set these two to off */ select @implicit_transaction = 0 select @close_cursor_at_commit = 0 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 /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) SELECT @drop_push_bit = 0 /* ** Check parameter and set expressions used by cursor */ /* Publisher */ IF @publisher IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher') RETURN (1) END IF @publisher = 'all' BEGIN SELECT @publisher_ex = '%' SELECT @expanded = 1 END ELSE BEGIN EXECUTE @retcode = dbo.sp_validname @publisher IF @retcode <> 0 RETURN (1) SELECT @publisher_ex = @publisher END /* Publisher_db */ IF @publisher_db IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher_db') RETURN (1) END IF @publisher_db = 'all' BEGIN SELECT @publisher_db_ex = '%' select @expanded = 1 END ELSE BEGIN /* EXECUTE @retcode = dbo.sp_validname @publisher_db IF @retcode <> 0 RETURN (1) */ SELECT @publisher_db_ex = @publisher_db END /* ** Publication ** '' is not a valid name but it may be in the publication name in the table. */ IF @publication IS NULL OR @publication = '' BEGIN SELECT @drop_null_pub = 1 END ELSE IF @publication = 'all' BEGIN SELECT @publication_ex = '%' SELECT @expanded = 1 SELECT @drop_null_pub = 1 END ELSE BEGIN EXECUTE @retcode = dbo.sp_validname @publication IF @retcode <> 0 RETURN (1) SELECT @publication_ex = @publication END /* ** Check to see if the subscription table exists */ IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND name = 'MSreplication_subscriptions') BEGIN IF @expanded = 0 BEGIN RAISERROR(14135, 11, -1, @publisher, @publisher_db, @publication) RETURN(1) END ELSE RETURN(0) END IF @expanded = 0 BEGIN /* ** ** Check to see if the subscription entry exists */ IF NOT EXISTS (SELECT * FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication) BEGIN RAISERROR(14135, 11, -1, @publisher, @publisher_db, @publication) RETURN(1) END /* ** Make sure the subscription is not push type if @drop_push_bit = 0 */ IF @drop_push_bit = 0 BEGIN IF EXISTS (SELECT * FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication AND subscription_type = @push AND @drop_push_bit = 0) BEGIN RAISERROR(20017, 16, -1) RETURN(1) END END END ELSE /* ** Open a cursor and call recursively if ** parameters are expanded. */ BEGIN /* ** Note: Any expression check on null value is false ** @subscription_type_id is NULL <==> push ** @subscription_type_id is NOT NULL <==> non push */ DECLARE hCdroppullsubscription CURSOR LOCAL FAST_FORWARD FOR SELECT DISTINCT publisher, publisher_db, publication FROM MSreplication_subscriptions WHERE ((@publisher_ex = N'%') OR (UPPER(publisher) = UPPER(@publisher_ex))) AND publisher_db LIKE @publisher_db_ex AND (publication LIKE @publication_ex OR (@drop_null_pub = 1 AND publication IS NULL)) AND ((@drop_push_bit =0 AND subscription_type <> @push) OR @drop_push_bit = 1) FOR READ ONLY OPEN hCdroppullsubscription FETCH hCdroppullsubscription INTO @publisher, @publisher_db, @publication WHILE (@@fetch_status <> -1) BEGIN EXECUTE @retcode = dbo.sp_droppullsubscription @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @reserved = 1 FETCH hCdroppullsubscription INTO @publisher, @publisher_db, @publication END CLOSE hCdroppullsubscription DEALLOCATE hCdroppullsubscription RETURN (0) END /* ** Only members of the sysadmin group and the creator of the distribution ** agent can drop a pull subscription successfully. This behavior matches ** the behavior of the sysjobs_view. DBO of the subscriber database, ** sysadmins (owner is undefined) can drop a subscription if the owner_sid ** is null. */ EXEC sp_MSget_pullsubsagent_owner @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @owner_sid = @owner_sid OUTPUT IF (@owner_sid is not null AND (SUSER_SID() <> @owner_sid) AND (ISNULL(IS_SRVROLEMEMBER('sysadmin'),0) = 0)) BEGIN SELECT @owner_name = SUSER_SNAME(@owner_sid) SELECT @qualified_publication_name = @publisher + N':' + @publisher_db + N':' + @publication RAISERROR(21121,16,-1,@owner_name, @qualified_publication_name) RETURN (1) END /* ** Get the agent name, it may be dropped later. */ SELECT @agent_id = agent_id FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication -- If the agent is used by other subscription, don't drop it. if (select count(*) from MSreplication_subscriptions where agent_id = @agent_id) > 1 select @agent_id = NULL begin tran save TRAN droppullsubscription /* ** Drop the subscription entry and the distribution agent if it exists */ /* ** If the distribution agent is not used anymore, ** drop the agent if it exists */ IF @agent_id IS NOT NULL BEGIN IF (EXISTS (SELECT * FROM msdb..sysjobs_view WHERE job_id = @agent_id)) BEGIN EXEC @retcode = msdb.dbo.sp_delete_job @job_id = @agent_id IF @@ERROR <> 0 or @retcode <> 0 GOTO UNDO -- Delete MSreplication_subsciptions table after dropping -- the distribution agent and delay one second -- to avoid deadlock with it. WAITFOR DELAY '00:00:01' END END /* Call sp_MSunregistersubscription so that the reg entries get deleted */ declare @subscriber_db sysname set @subscriber_db = DB_NAME() exec @retcode = dbo.sp_MSunregistersubscription @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @subscriber = @@SERVERNAME, @subscriber_db = @subscriber_db IF @retcode<>0 or @@ERROR<>0 GOTO UNDO /* -- Delete MSreplication_subsciptions table after dropping the distribution agent\ -- To avoid deadlock with it. --DELETE MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND --publisher_db = @publisher_db AND --publication = @publication --IF @@ERROR <> 0 -- GOTO UNDO */ IF EXISTS(select * from sysobjects where type='U' and name = 'MSsubscription_properties') BEGIN DELETE FROM MSsubscription_properties WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication IF @@ERROR <> 0 GOTO UNDO IF NOT EXISTS (SELECT * FROM MSsubscription_properties) BEGIN DROP TABLE MSsubscription_properties IF @@ERROR <> 0 GOTO UNDO END END /* ** Clean up metadata at subscriber side */ exec @retcode = dbo.sp_subscription_cleanup @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication IF @retcode<>0 or @@ERROR<>0 GOTO UNDO -- -- drop table MSreplication_subscriptions if empty and -- not in recursive call -- IF (@reserved = 0 AND NOT EXISTS (SELECT * FROM MSreplication_subscriptions)) BEGIN DROP TABLE MSreplication_subscriptions IF @@ERROR <> 0 GOTO UNDO END COMMIT TRAN /* ** set back the two settings if needed */ 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) UNDO: IF @@TRANCOUNT > 0 begin ROLLBACK TRAN droppullsubscription COMMIT TRAN end /* ** set back the two settings if needed */ 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 grant execute on dbo.sp_droppullsubscription to public go -------------------------------------------------------------------------------- --. sp_addmergepullsubscription -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_addmergepullsubscription') drop procedure sp_addmergepullsubscription go raiserror('Creating procedure sp_addmergepullsubscription', 0,1) GO CREATE PROCEDURE sp_addmergepullsubscription ( @publication sysname, /* Publication name */ @publisher sysname = @@SERVERNAME, /* Publisher server */ @publisher_db sysname = NULL, /* Publication database */ @subscriber_type nvarchar(15) = 'local', /* Subscriber type */ @subscription_priority real = NULL, /* Subscription priority */ @sync_type nvarchar(15) = 'automatic', /* subscription sync type */ @description nvarchar(255) = NULL ) AS SET NOCOUNT ON /* ** Declarations. */ declare @retcode int declare @subscriber_db sysname declare @subnickname int declare @subscriber_srvid int declare @publisher_srvid int declare @priority real declare @subid uniqueidentifier declare @subscriber_typeid smallint declare @subscription_type smallint declare @command nvarchar(255) declare @inactive tinyint declare @global tinyint /* subscriber type is global */ declare @push tinyint /* subscription type is push */ declare @sync_typeid tinyint declare @nosync tinyint declare @automatic tinyint declare @pubid uniqueidentifier declare @partnerid uniqueidentifier declare @parentid uniqueidentifier /* ** Initializations. */ SET @nosync = 2 /* Const: synchronization type 'nosync' */ SET @automatic = 1 /* Const: synchronization type 'automatic' */ SET @inactive = 0 SET @global = 1 SET @push = 0 set @pubid = newid() set @partnerid = @pubid set @parentid = '00000000-0000-0000-0000-000000000000' /* ** Check if replication components are installed on this server */ exec @retcode = dbo.sp_MS_replication_installed if (@retcode <> 1) begin return (1) end /* ** Security Check. */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Check to see if merge system tables exist. Create them unless they already ** exist. */ 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 if UPPER(@publisher) = UPPER(@@SERVERNAME) and @publisher_db = db_name() begin raiserror(21126, 16, -1) return (1) end if exists (select pubid from sysmergepublications where UPPER(publisher) = UPPER(@@SERVERNAME) and publisher_db=db_name()) and @subscriber_type in ('local', 'anonymous') begin declare @dbname sysname select @dbname = DB_NAME() raiserror(21127, 16, -1, @dbname) return (1) end /* ** When adding a pull subscription, if a push subscription for that publication already exists, ** we will cleanup all the traces of that subscription */ IF EXISTS (select name from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db) BEGIN select @pubid=pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db IF EXISTS (select subid from sysmergesubscriptions where pubid=@pubid and subid<>@pubid and subscription_type=0) begin exec @retcode = dbo.sp_MSpublicationcleanup @publisher=@publisher, @publisher_db=@publisher_db, @publication=@publication IF @@ERROR <> 0 or @retcode <>0 BEGIN RAISERROR (20025, 16, -1, @publication) return (1) END end ELSE begin IF EXISTS (select status from sysmergesubscriptions where pubid=@pubid and status = 2) begin select @subid = subid from sysmergesubscriptions where pubid=@pubid and subid<>pubid delete sysmergesubscriptions where pubid=@pubid delete MSmerge_replinfo where repid = @subid end ELSE begin RAISERROR (14058, 16, -1) return (1) end end END set @partnerid = @pubid /* ** Assign parameter values appropriately for the local server database */ set @subscriber_db = DB_NAME() select @subscriber_srvid = 0 /* ** 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 IF LOWER(@publisher) = 'all' BEGIN RAISERROR (14136, 16, -1) RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publisher IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) /* ** 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 EXECUTE @retcode = dbo.sp_addserver @publisher IF @@error <> 0 OR @retcode <> 0 BEGIN RAISERROR (14010, 16, -1) RETURN (1) END ELSE select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher) END /* ** Parameter Check: @publisher_db */ IF @publisher_db IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher_db') RETURN (1) END IF LOWER(@publisher_db) = 'all' BEGIN RAISERROR (14136, 16, -1) RETURN (1) END /* ** Check to see if the publication name is already used in the subscription ** database - This is the case where we are resubscribing to the same publication. ** Execute dbo.sp_MSpublicationcleanup to cleanup all all the defunct rows ** if exists (select * from sysmergepublications where name = @publication) ** begin ** exec @retcode = dbo.sp_MSpublicationcleanup ** IF @@ERROR <> 0 OR @retcode <> 0 ** BEGIN ** RAISERROR (20025, 16, -1, @publication) ** RETURN (1) ** END ** end */ /* ** Parameter Check: @subscriber_type. ** Set subscriber_typeid based on the @subscriber_type specified. ** ** subscriber_type subscriber_type ** ================= =============== ** 1 global ** 2 local ** 3 anonymous ** NO support for republisher for B 3 */ if LOWER(@subscriber_type) NOT IN ('local', 'global', 'anonymous') BEGIN RAISERROR (20023, 16, -1) RETURN (1) END set @subscription_type = 1 /* pull by default */ 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') begin /* For anonymous subscribers set subscription type appropriately */ set @subscriber_typeid = 3 set @subscription_type = 2 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) set @subscription_priority = NULL if (@subscription_priority IS NULL) begin select @priority = 0.99 * min(priority) from sysmergesubscriptions where subscriber_type = 1 /* global/loopback */ 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 /* ** If the subscription already exists, don't add it. ** if EXISTS (select db_name, srvid ** FROM sysmergesubscriptions ** WHERE db_name = @subscriber_db ** AND srvid = @subscriber_srvid ** AND pubid = @pubid) ** BEGIN ** RAISERROR (14058, 16, -1) ** RETURN (1) ** END */ /* ** 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 LOWER(@sync_type) = 'automatic' BEGIN SET @sync_typeid = @automatic END ELSE BEGIN SET @sync_typeid = @nosync END /* ** UNDONE: Validate that the publisher is of type 'republisher' */ begin tran save TRAN addmergepullsubscription /* Generate a guid for the Subscriber ID */ set @subid = newid() /* Look for existing nickname from any other subscription */ exec dbo.sp_MSgetreplnick NULL, NULL , NULL, @subnickname out if (@@error <> 0) begin goto FAILURE end /* Generate a new replica nickname from the @subid */ if (@subnickname is null) EXECUTE dbo.sp_MSgenreplnickname @subid, @subnickname output /* ** Check to see if MSsubscription_properties table exists. ** If not, create it. */ exec @retcode = dbo.sp_MScreate_sub_tables IF @@ERROR <> 0 or @retcode <> 0 goto FAILURE /* ** The subscription doesn't exist, so let's add it to sysmergesubscriptions */ INSERT sysmergesubscriptions (subid, partnerid, datasource_type, srvid, db_name, pubid, status, subscriber_type, subscription_type, priority, sync_type, description, login_name) VALUES (@subid, @partnerid, 0, @subscriber_srvid, @subscriber_db, @pubid, @inactive, @subscriber_typeid, @subscription_type, /* for a pull/anon subscription */ @subscription_priority, @sync_typeid, @description, suser_sname(suser_sid())) if @@ERROR <> 0 BEGIN GOTO FAILURE END /* Add a self-subscribed subscription to represent the publication */ insert sysmergepublications(publisher, publisher_db, pubid, name, parentid) values(@publisher, @publisher_db, @pubid, @publication, @parentid) if @@ERROR <> 0 begin goto FAILURE end insert sysmergesubscriptions(subid, partnerid, datasource_type, srvid, db_name, pubid, subscriber_type, subscription_type, status, priority, sync_type, description, login_name) values (@pubid, @pubid, 0, @publisher_srvid, @publisher_db, @pubid, @global, @push, @inactive, 100.0, @sync_typeid, @description, suser_sname(suser_sid())) if @@ERROR <> 0 begin goto FAILURE end /* ** Add row for subscription in MSmerge_replinfo. */ insert MSmerge_replinfo(repid, replnickname) values (@subid, @subnickname) if @@ERROR <> 0 BEGIN GOTO FAILURE END COMMIT TRAN return (0) FAILURE: RAISERROR (14057, 16, -1) if @@trancount > 0 begin ROLLBACK TRANSACTION addmergepullsubscription COMMIT TRANSACTION end RETURN (1) go grant execute on dbo.sp_addmergepullsubscription to public go -------------------------------------------------------------------------------- --. sp_helpmergepullsubscription -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_helpmergepullsubscription') drop procedure sp_helpmergepullsubscription go raiserror('Creating procedure sp_helpmergepullsubscription', 0,1) GO CREATE PROCEDURE sp_helpmergepullsubscription( @publication sysname = '%', /* Publication name */ @publisher sysname = '%', /* Publisher server */ @publisher_db sysname = '%', /* Publication database */ @subscription_type nvarchar(10) = 'pull' /* Show only pull subscriptions */ )AS SET NOCOUNT ON /* ** Declarations. */ declare @retcode int declare @srvid int declare @pubid uniqueidentifier declare @subid uniqueidentifier declare @partnerid uniqueidentifier declare @cursor_open int declare @subscriber sysname declare @subscriber_db sysname declare @subscription_set nvarchar(10) declare @publisher_local sysname declare @publisher_db_local sysname declare @publication_local sysname declare @subscription_name nvarchar(1000) declare @regkey nvarchar(1000) declare @time smalldatetime declare @syncmgr_keyexist int declare @helpsubscriptioncursor_open int /* ** Initializations. */ set @cursor_open = 0 select @publisher_db = RTRIM(@publisher_db) select @publication = RTRIM(@publication) /* ** 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_subscribe if @@ERROR <> 0 or @retcode <> 0 return(1) set @subscriber = @@SERVERNAME set @subscriber_db = DB_NAME() /* ** Parameter Check: @publisher ** Check to make sure that the publisher is defined */ IF @publisher <> '%' AND @publisher IS NOT NULL BEGIN EXECUTE @retcode = dbo.sp_validname @publisher IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) 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 /* ** Parameter Check: @subscription_type. ** Set subscription_typeid based on the @subscription_type specified. ** ** subscription_type subscription_type ** ================= =============== ** 0 push ** 1 pull ** 0,1 both */ if LOWER(@subscription_type) NOT IN ('push', 'pull', 'both') BEGIN RAISERROR (14128, 16, -1) RETURN (1) END IF LOWER(@subscription_type) = 'both' set @subscription_set = '(0, 1)' else IF LOWER(@subscription_type) = 'push' set @subscription_set = '(0)' else set @subscription_set = '(1,2)' -- including pull subscription and pull/anonymous subscription /* ** Get subscriptions */ create table #helpmergepullsubscription ( 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, enabled_for_syncmgr int NULL, last_updated nvarchar(40) NULL ) IF @publisher IS NULL and @publisher_db IS NULL BEGIN select @subid = subid from sysmergesubscriptions where subid = partnerid set @partnerid = @subid -- show the loopback subscription insert into #helpmergepullsubscription select 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, 0, NULL FROM sysmergesubscriptions subs1, sysmergesubscriptions subs2, MSmerge_replinfo replinfo, master..sysservers servers1, master..sysservers servers2, sysmergepublications pubs where subs1.subid = @subid and subs2.subid = @partnerid and pubs.pubid = subs1.pubid and servers1.srvid = subs1.srvid and servers2.srvid = subs2.srvid and subs1.subid = subs1.partnerid and replinfo.repid = subs1.subid END else begin declare #cursor cursor local FAST_FORWARD FOR select DISTINCT sub.subid, sub.partnerid FROM sysmergesubscriptions sub, sysmergesubscriptions sub1, master..sysservers ss, master..sysservers ss1, sysmergepublications pub WHERE ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber))) AND ((@publisher = N'%') OR (UPPER(ss1.srvname) = UPPER(@publisher))) AND sub1.srvid = ss1.srvid AND sub.srvid = ss.srvid AND pub.name LIKE @publication AND sub.pubid = pub.pubid AND sub.db_name LIKE @subscriber_db AND sub1.db_name LIKE @publisher_db AND sub1.pubid = pub.pubid AND (sub.subscription_type=1 or sub.subscription_type=2) FOR READ ONLY open #cursor select @cursor_open = 1 fetch next from #cursor into @subid, @partnerid while (@@fetch_status <> -1) begin insert into #helpmergepullsubscription select 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, 0, NULL FROM sysmergesubscriptions subs1, sysmergesubscriptions subs2, MSmerge_replinfo replinfo, master..sysservers servers1, master..sysservers servers2, sysmergepublications pubs where subs1.subid = @subid and subs2.subid = @partnerid and pubs.pubid = subs1.pubid and servers1.srvid = subs1.srvid and servers2.srvid = subs2.srvid and @subid <> @partnerid -- do not show the loopback subscription and replinfo.repid = subs1.subid if @@ERROR <> 0 begin set @retcode = 1 goto DONE end fetch next from #cursor into @subid, @partnerid end end declare #helpsubscriptioncursor CURSOR LOCAL FAST_FORWARD FOR select DISTINCT publisher, publisher_db, publication FROM #helpmergepullsubscription FOR READ ONLY create table #syncmgr_keyexist (syncmgr_keyexist int) open #helpsubscriptioncursor select @helpsubscriptioncursor_open = 1 fetch next from #helpsubscriptioncursor into @publisher_local, @publisher_db_local, @publication_local while (@@fetch_status <> -1) begin set @subscription_name = @publisher_local + ':' + @publisher_db_local + ':' + @publication_local + ':' + @subscriber + ':' + @subscriber_db /* Replace back slash with forward slash so that the key name is a valid REGISTRY key name */ set @subscription_name = REPLACE(@subscription_name,'\','/') set @regkey = 'SOFTWARE\Microsoft\MSSQLServer\Replication\Subscriptions\' + @subscription_name insert into #syncmgr_keyexist EXECUTE master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @regkey select @syncmgr_keyexist = syncmgr_keyexist from #syncmgr_keyexist update #helpmergepullsubscription set enabled_for_syncmgr = @syncmgr_keyexist where UPPER(publisher) = UPPER(@publisher_local) and publisher_db = @publisher_db_local and publication = @publication_local select @pubid = pubid from sysmergepublications where name=@publication_local and UPPER(publisher) = UPPER(@publisher_local) and publisher_db = @publisher_db_local select @time=max(coldate) from MSmerge_genhistory where art_nick in (select nickname from sysmergearticles where pubid=@pubid) update #helpmergepullsubscription set last_updated = convert(nvarchar(12), @time, 112) + substring(convert(nvarchar(24), @time, 121), 11,13) where UPPER(publisher) = UPPER(@publisher_local) and publisher_db = @publisher_db_local and publication = @publication_local fetch next from #helpsubscriptioncursor into @publisher_local, @publisher_db_local, @publication_local end select 'subscription_name'= publisher + ':' + publisher_db + ':' + publication, * from #helpmergepullsubscription order by publisher, publisher_db, publication, subscriber, subscriber_db select @retcode = 0 DONE: if (@cursor_open = 1) begin close #cursor deallocate #cursor end drop table #helpmergepullsubscription if (@helpsubscriptioncursor_open = 1) begin close #helpsubscriptioncursor deallocate #helpsubscriptioncursor end drop table #syncmgr_keyexist return @retcode go grant execute on dbo.sp_helpmergepullsubscription to public go -------------------------------------------------------------------------------- --. sp_dropmergepullsubscription -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_dropmergepullsubscription') drop procedure sp_dropmergepullsubscription go raiserror('Creating procedure sp_dropmergepullsubscription', 0,1) GO CREATE PROCEDURE sp_dropmergepullsubscription( @publication sysname = NULL, /* Publication name */ @publisher sysname = NULL, /* Publisher server */ @publisher_db sysname = NULL, /* Publication database */ @reserved bit = 0 )AS SET NOCOUNT ON /* ** Declarations. */ declare @retcode int declare @subscriber_srvid int declare @publisher_srvid int declare @pubid uniqueidentifier declare @subid uniqueidentifier declare @partnerid uniqueidentifier declare @local_server sysname declare @local_db sysname declare @merge_jobid binary(16) declare @cmd nvarchar(255) declare @pubidstr nvarchar(38) declare @subscriber sysname declare @subscriber_db sysname declare @subscriber_type int declare @local_job bit declare @implicit_transaction int declare @close_cursor_at_commit int declare @owner_sid varbinary(85) declare @owner_name sysname declare @qualified_publication_name nvarchar(512) select @close_cursor_at_commit = 0 select @implicit_transaction = 0 /* ** Get original setting values before setting them to false for recursive calling */ 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 /* ** Security Check. */ exec @retcode = dbo.sp_MSreplcheck_subscribe if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Initializations. */ set @local_db = DB_NAME() set @local_server = @@SERVERNAME set @subscriber = @@SERVERNAME set @subscriber_db = DB_NAME() /* ** Assign parameter values appropriately */ 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 not exists (select name from sysobjects where name='sysmergesubscriptions') BEGIN RAISERROR (14055, 16, -1) RETURN (1) END /* ** 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 /* ** 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 FOR READ ONLY OPEN hC1 FETCH hC1 INTO @publication if @@fetch_status = -1 begin CLOSE hC1 DEALLOCATE hC1 RETURN (0) --- It's OK to have no publication when 'ALL' end WHILE (@@fetch_status <> -1) BEGIN EXECUTE dbo.sp_dropmergepullsubscription @publication = @publication, @publisher = @publisher, @publisher_db = @publisher_db, @reserved = 1 FETCH hC1 INTO @publication END CLOSE hC1 DEALLOCATE hC1 RETURN (0) END IF LOWER(@publisher) = 'all' BEGIN declare hC4 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT srvname FROM master..sysservers FOR READ ONLY OPEN hC4 FETCH hC4 INTO @publisher WHILE (@@fetch_status <> -1) BEGIN EXECUTE dbo.sp_dropmergepullsubscription @publication = @publication, @publisher = @publisher, @publisher_db = @publisher_db, @reserved = 1 FETCH hC4 INTO @publisher END CLOSE hC4 DEALLOCATE hC4 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 /* Previously the condition is set as 'AND subid<>pubid' which is fatally errorous */ IF LOWER(@publisher_db) = 'all' BEGIN declare hC5 CURSOR LOCAL FAST_FORWARD FOR select DISTINCT db_name FROM sysmergesubscriptions WHERE subid = pubid and pubid in (select pubid from sysmergepublications where UPPER(publisher)=UPPER(@publisher) and name=@publication) FOR READ ONLY OPEN hC5 FETCH hC5 INTO @publisher_db WHILE (@@fetch_status <> -1) BEGIN EXECUTE dbo.sp_dropmergepullsubscription @publication = @publication, @publisher = @publisher, @publisher_db = @publisher_db, @reserved = 1 FETCH hC5 INTO @publisher_db END CLOSE hC5 DEALLOCATE hC5 RETURN (0) END /* ** return error if only there is no 'ALL'. Same is true for the rest of error handling. */ if NOT EXISTS (select * FROM sysmergepublications WHERE name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db) BEGIN if @reserved = 0 RAISERROR (20026, 16, -1, @publication) RETURN (1) END select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db set @pubidstr = '''' + convert(nchar(36), @pubid) + '''' if @pubid is null BEGIN if @reserved = 0 RAISERROR (20026, 16, -1, @publication) RETURN (1) END /* ** Only members of the sysadmin group and the creator of the distribution ** agent can drop a pull subscription successfully. This behavior matches ** the behavior of the sysjobs_view. DBO of the subscriber database, ** sysadmins (owner is undefined) can drop a subscription if the owner_sid ** is null. */ EXEC sp_MSget_mergepullsubsagent_owner @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @owner_sid = @owner_sid OUTPUT IF (@owner_sid is not null AND (SUSER_SID() <> @owner_sid) AND (ISNULL(IS_SRVROLEMEMBER('sysadmin'),0) = 0)) BEGIN SELECT @owner_name = SUSER_SNAME(@owner_sid) SELECT @qualified_publication_name = @publisher + N':' + @publisher_db + N':' + @publication RAISERROR(21121,16,-1,@owner_name, @qualified_publication_name) RETURN (1) END /* ** Get subscriptions from either local replicas or global replicas */ select @subid = subs1.subid, @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(@publisher) and pubs.publisher_db=@publisher_db if @subid IS NULL begin if @reserved = 0 raiserror (14050, 16, -1) RETURN (0) end begin tran save TRAN dropmergepullsubscription /* ** Drop the local merge task */ select @merge_jobid = merge_jobid from MSmerge_replinfo WHERE repid = @subid if (@merge_jobid IS NOT NULL) BEGIN IF EXISTS (SELECT * FROM msdb..sysjobs_view WHERE job_id = @merge_jobid) BEGIN EXEC @retcode = msdb.dbo.sp_delete_job @job_id = @merge_jobid IF @@ERROR <> 0 or @retcode <> 0 GOTO FAILURE END END if @subid <> @partnerid BEGIN DELETE MSmerge_replinfo WHERE repid = @subid IF @@ERROR <> 0 GOTO FAILURE delete from sysmergesubscriptions where subid = @subid if @@ERROR <> 0 GOTO FAILURE /* Call sp_MSunregistersubscription so that the reg entries get deleted */ exec @retcode = dbo.sp_MSunregistersubscription @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @subscriber = @@SERVERNAME, @subscriber_db = @subscriber_db IF @retcode<>0 or @@ERROR<>0 GOTO FAILURE exec dbo.sp_MSpublicationcleanup @publisher=@publisher, @publisher_db = @publisher_db, @publication = @publication IF @@ERROR <> 0 BEGIN RAISERROR (20025, 16, -1, @publication) GOTO FAILURE END END IF EXISTS(select * from sysobjects where type='U' and name = 'MSsubscription_properties') BEGIN DELETE FROM MSsubscription_properties WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication IF @@ERROR <> 0 GOTO FAILURE IF NOT EXISTS (SELECT * FROM MSsubscription_properties) BEGIN DROP TABLE MSsubscription_properties IF @@ERROR <> 0 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: RAISERROR (14056, 16, -1) if @@trancount > 0 begin ROLLBACK TRANSACTION dropmergepullsubscription 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 grant execute on dbo.sp_dropmergepullsubscription to public go -------------------------------------------------------------------------------- --. sp_MSreplraiserror -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSreplraiserror') drop procedure sp_MSreplraiserror go raiserror('Creating procedure sp_MSreplraiserror', 0,1) go create proc sp_MSreplraiserror @errorid int, @param1 sysname = null, @param2 sysname= null as if @errorid = 20508 raiserror (20508, 16, 1) else if @errorid = 20509 raiserror (20509, 16, 1) else if @errorid = 20510 raiserror (20510, 16, 1) else if @errorid = 20511 raiserror (20511, 16, 1) else if @errorid = 20512 raiserror (20512, 16, 1) else if @errorid = 20515 raiserror (20515, 16, 1) else if @errorid = 20516 raiserror (20516, 16, 1) else if @errorid = 20517 raiserror (20517, 16, 1) else if @errorid = 20518 raiserror (20518, 16, 1) else if @errorid = 20519 raiserror (20519, 16, 1) else if @errorid = 20520 raiserror (20520, 16, 1) else if @errorid = 21034 raiserror (21034, 16, 1) else if @errorid = 21054 raiserror (21054, 16, 1) else if @errorid = 21161 raiserror (21161, 16, 1) go grant exec on dbo.sp_MSreplraiserror to public go -------------------------------------------------------------------------------- --. sp_MSget_col_position -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSget_col_position') drop procedure sp_MSget_col_position go raiserror('Creating procedure sp_MSget_col_position', 0,1) go create procedure sp_MSget_col_position @objid int, @columns binary(32), @key sysname, @colpos sysname output, @art_col int = NULL output, @get_num_col bit = 0, @num_col int = NULL output, @this_col int = null output as declare @colname sysname declare @ccoltype sysname declare @src_cols int declare @rc int select @src_cols = count(*) from syscolumns where id = @objid select @this_col = 1 select @num_col = 0 while @this_col <= @src_cols begin exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 1, @colname output, @ccoltype output if @rc = 0 begin set @num_col = @num_col + 1 -- If @get_num_col is 1, we just need the number of columns in the partition. if @get_num_col = 0 and @colname = @key begin select @colpos = 'c' + convert(varchar(4), @this_col) set @art_col = @num_col break end end set @this_col = @this_col + 1 end return 0 go -------------------------------------------------------------------------------- --. sp_MSscript_where_clause -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSscript_where_clause') drop procedure sp_MSscript_where_clause go raiserror('Creating procedure sp_MSscript_where_clause', 0,1) go create procedure sp_MSscript_where_clause @objid int, @columns binary(32), @clause_type varchar(6) = 'pk_new', -- 'new pk', 'old pk', 'upd ts', 'upd rc', 'trg pk' @ts_col sysname = NULL, @indent int = 0, @op_type char(3) = NULL -- 'ins', 'del' as declare @cmd nvarchar(4000) declare @colname sysname declare @ccoltype sysname declare @spacer nvarchar(20) declare @indkey int declare @indid int declare @key sysname declare @rc int declare @this_col int declare @art_col int declare @src_cols int declare @col sysname declare @qualname nvarchar(512) select @spacer = N' ', @cmd = N'' select @indkey = 1, @indid = 0 exec sp_MSget_qualified_name @objid, @qualname OUTPUT select @src_cols = count(*) from syscolumns where id = @objid exec dbo.sp_MSpad_command @cmd output, @indent select @cmd = @cmd + N'where' exec dbo.sp_MSflush_command @cmd output, 1, @indent if @clause_type in ('new pk', 'old pk', 'upd ts', 'trg pk') begin exec @indid = dbo.sp_MStable_has_unique_index @objid if @indid > 0 begin while @indkey < 16 and index_col(@qualname, @indid, @indkey) is not null begin select @key = index_col(@qualname, @indid, @indkey) --exec dbo.sp_MSget_col_position @objid, @columns, @key, @col output, @this_col output exec dbo.sp_MSget_col_position @objid, @columns, @key, @col output, NULL, 0, NULL, @this_col output if @clause_type = 'new pk' begin if ColumnProperty(@objid, @key, 'IsIdentity') = 1 select @cmd = @cmd + @spacer + quotename(@key) + N' = @@identity' else select @cmd = @cmd + @spacer + quotename(@key) + N' = @' + @col select @spacer = ' and ' end else if @clause_type = 'upd ts' begin select @cmd = @cmd + @spacer + quotename(@key) + N' = @' + @col + N'_old' select @spacer = ' and ' end else if @clause_type in ('trg pk', 'old pk') begin if @op_type = 'ins' select @cmd = @cmd + @spacer + quotename(@key) + N' = @' + @col + N'_old' else -- The vars correspoding to pk were set in sp_MSscript -- _pkvar_assignment. select @cmd = @cmd + @spacer + quotename(@key) + N' = @' + @col select @spacer = ' and ' end select @indkey = @indkey + 1 -- flush command if necessary exec dbo.sp_MSflush_command @cmd output, 0, @indent end end -- if clause_type is 'upd ts', add timestamp col if @clause_type = 'upd ts' begin exec dbo.sp_MSget_col_position @objid, @columns, @ts_col, @col output select @cmd = @cmd + @spacer + @ts_col + N' = @' + @col + N'_old' end -- save off command fragment exec dbo.sp_MSflush_command @cmd output, 1, @indent end else if @clause_type = 'upd rc' begin select @this_col = 1, @art_col = 1 while @this_col <= @src_cols begin exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output if @rc = 0 begin select @cmd = @cmd + @spacer + '(' + @colname + N' = @c' + convert(varchar(4), @this_col) + N'_old or (' select @cmd = @cmd + @colname + ' is null and @c' + convert(varchar(4), @this_col) + N'_old is null)) ' select @spacer = N' and ' exec dbo.sp_MSflush_command @cmd output, 0, @indent end exec dbo.sp_MSflush_command @cmd output, 1, @indent select @this_col = @this_col + 1 end -- save off cmd fragment exec dbo.sp_MSflush_command @cmd output, 1, @indent end go grant execute on dbo.sp_MSscript_where_clause to public go -------------------------------------------------------------------------------- --. sp_MSscript_trigger_update_checks -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSscript_trigger_update_checks') drop procedure sp_MSscript_trigger_update_checks go raiserror('Creating procedure sp_MSscript_trigger_update_checks', 0,1) go create procedure sp_MSscript_trigger_update_checks @objid int, @identity_col sysname, @ts_col sysname, @op_type varchar(3) = 'ins', -- 'pk', 'ins', 'upd' @indent int = 0 as declare @cmd nvarchar(4000) declare @colname sysname declare @ccoltype sysname declare @src_cols int declare @this_col int declare @rc int declare @qualname nvarchar(512) declare @indid int declare @key sysname declare @indkey int if @op_type = 'pk' begin select @indkey = 1 exec sp_MSget_qualified_name @objid, @qualname OUTPUT exec @indid = dbo.sp_MStable_has_unique_index @objid if @indid > 0 begin exec dbo.sp_MSpad_command @cmd output, @indent while @indkey < 16 and index_col(@qualname, @indid, @indkey) is not null begin select @key = index_col(@qualname, @indid, @indkey) select @cmd = N'if update(' + @key + N') ' exec dbo.sp_MSflush_command @cmd output, 1, @indent insert into #proctext(procedure_text) values(N'begin exec sp_MSreplraiserror 20517 goto FAILURE end ') select @indkey = @indkey + 1 end end end else begin -- Image cols select @src_cols = count(*) from syscolumns where id = @objid select @this_col = 1 exec dbo.sp_MSpad_command @cmd output, @indent while @this_col <= @src_cols begin exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, null, 1, @colname output, @ccoltype output if @rc = 0 and EXISTS (select name from syscolumns where id=@objid and @this_col=colid and iscomputed<>1) begin if @ccoltype in ('text','ntext','image') begin if @op_type = 'ins' begin select @cmd = N'if update(' + quotename(@colname) + ') ' exec dbo.sp_MSflush_command @cmd output, 1, 0 insert into #proctext(procedure_text) values(N' exec sp_MSreplraiserror 20508 ') end else if @op_type = 'upd' begin select @cmd = N'if update(' + quotename(@colname) + ') ' exec dbo.sp_MSflush_command @cmd output, 1, 0 insert into #proctext(procedure_text) values(N'begin exec sp_MSreplraiserror 20509 goto FAILURE end ') end end end select @this_col = @this_col + 1 end end -- identity col if @op_type = 'upd' and @identity_col is not null begin select @cmd = N'if update(' + quotename(@identity_col) + N') ' exec dbo.sp_MSflush_command @cmd, 1 insert into #proctext(procedure_text) values(N'begin exec sp_MSreplraiserror 20510 goto FAILURE end ') end -- timestamp col if @op_type = 'upd' and @ts_col is not null begin select @cmd = N'if update(' + quotename(@ts_col) + N') ' exec dbo.sp_MSflush_command @cmd, 1 insert into #proctext(procedure_text) values(N'begin exec sp_MSreplraiserror 20511 goto FAILURE end ') end go grant execute on dbo.sp_MSscript_trigger_update_checks to public go -------------------------------------------------------------------------------- --. sp_MSget_synctran_column -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSget_synctran_column') drop procedure sp_MSget_synctran_column go raiserror('Creating procedure sp_MSget_synctran_column', 0,1) go create procedure sp_MSget_synctran_column @ts_col sysname, @op_type char(3), -- 'ins, 'upd', 'del' @is_new bit, @primary_key_bitmap varbinary(4000), @colname sysname, @this_col int, -- position in the table @column nvarchar(4000) output, @from_proc bit = 0, @coltype sysname = NULL, @type varchar(10) = NULL, @art_col int = null -- position in the article partition. as declare @bytestr nvarchar(10) declare @bitstr nvarchar(10) declare @typed_null nvarchar(255) if @coltype is null select @typed_null = 'NULL' else select @typed_null = 'convert(' + @coltype + ', NULL)' -- Optimization: -- If the column value is not needed, we set the corresponding -- param to null to reduce the network traffic. Here is the rule: -- For new values in update trigger, -- Set the param to column value or null depending on whether or -- or the column is updated. -- For old values -- if ts col is replicated and the current column is not the ts col -- and the column is not in primary key, set the param to null -- For other cases -- set the param to column values. -- Called by proc if @type = 'pk_var' begin select @bytestr = convert( nvarchar, 1 + (@this_col-1) / 8 ) select @bitstr = convert( nvarchar, power(2, (@this_col-1) % 8 ) ) select @column = N'case substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr + N' when ' + @bitstr + N' then ' + N'@c'+ convert( nvarchar, @this_col ) + N' else ' + N'@c'+ convert( nvarchar, @this_col ) + N'_old end' end else if (@from_proc = 1) begin select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 ) select @bitstr = convert( nvarchar, power(2, (@art_col-1) % 8 ) ) select @column = N'case substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr + N' when ' + @bitstr + N' then ' + N'@c'+ convert( nvarchar, @this_col ) + N' else [' + @colname + N'] end' end -- Called in trigger, else if (@is_new = 1) and (@op_type = 'upd') begin -- @bitmap is set using columns_updated() at the beginning -- of the trigger. select @bytestr = convert( nvarchar, 1 + (@this_col-1) / 8 ) select @bitstr = convert( nvarchar, power(2, (@this_col-1) % 8 ) ) select @column = N'case substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr + N' when ' + @bitstr + N' then [' + @colname + N'] ' + N' else ' + @typed_null +' end' end else if @is_new = 0 and @ts_col is not null and @colname <> @ts_col and (substring(@primary_key_bitmap, 1 + (@this_col-1) / 8 , 1) & power(2, (@this_col-1) % 8 )) = 0 select @column = @typed_null else select @column = N'[' + @colname + N'] ' -- Add a new line select @column = @column + N' ' go -------------------------------------------------------------------------------- --. sp_addsynctriggers -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_addsynctriggers') drop procedure sp_addsynctriggers go raiserror('Creating procedure sp_addsynctriggers', 0,1) go CREATE PROCEDURE sp_addsynctriggers @sub_table sysname, -- table name @sub_table_owner sysname, -- table owner @publisher sysname, -- publishing server name @publisher_db sysname, -- publishing database name. If NULL then same as current db @publication sysname, -- publication name. @ins_proc sysname, @upd_proc sysname, @del_proc sysname, @proc_owner sysname, @identity_col sysname = 'NULL', @ts_col sysname = 'NULL', @filter_clause nvarchar(4000) = 'NULL', @primary_key_bitmap varbinary(4000) AS set nocount on declare @db sysname declare @trigname sysname declare @ins_trig sysname declare @upd_trig sysname declare @del_trig sysname declare @dbname sysname declare @ccols int declare @cnt int declare @retcode int declare @cmd nvarchar(4000) declare @merge_pub_object_bit int declare @synctran_bit int declare @object_id int declare @bitmap_str varchar(8000) declare @constraint_name sysname declare @quoted_name nvarchar(500) declare @qualname nvarchar(500) select @merge_pub_object_bit = 128 select @synctran_bit = 256 -- Security Check EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) -- Dist Agent executes this sproc with 'implicit transasctions on'. -- We take care of our own transactions boundaries to get out of tran while @@trancount > 0 commit tran -- check valid server and database setting -- 1. nested trigger have to be on if exists (select * from master..sysconfigures where config = 115 and value = 0) begin raiserror(21081, 16, 1) return (1) end -- 2. db option: recursive trigger have to be off if DATABASEPROPERTY(db_name(), N'IsRecursiveTriggersEnabled') <> 0 begin raiserror(21082, 16, 1) return (1) end -- 2. db compatibility level have to be 7.0 if exists (select * from master..sysdatabases where dbid = db_id() and cmptlevel < 70) begin raiserror(21083, 16, 1) return (1) end if lower(@sub_table_owner) = N'null' select @qualname = QUOTENAME(@sub_table) else select @qualname = QUOTENAME(@sub_table_owner) + N'.' + QUOTENAME(@sub_table) -- Verify that table exists select @object_id = object_id (@qualname) if @object_id is null begin raiserror(20507, 16, 1, @qualname, 'sp_addsynctriggers') return (1) end -- Add default to timestamp and identity column select @constraint_name = 'MSrepl_synctran_ts_default_' + convert(nvarchar(10), @object_id) select @quoted_name = quotename(@ts_col) if @ts_col is not null and @ts_col not in ('null','NULL') and not exists (select * from sysobjects where name = @constraint_name) begin exec ('alter table ' + @qualname + ' add constraint ' + @constraint_name + ' default 0 for ' + @quoted_name ) if @@ERROR<>0 return 1 end select @constraint_name = 'MSrepl_synctran_identity_default_' + convert(nvarchar(10), @object_id) select @quoted_name = quotename(@identity_col) if @identity_col is not null and @identity_col not in ('null','NULL') and not exists (select * from sysobjects where name = @constraint_name) begin exec ('alter table ' + @qualname + ' add constraint ' + @constraint_name + ' default 0 for ' + @quoted_name ) if @@ERROR<>0 return 1 end -- If MSsubscription_properties table does not exists, create on. exec @retcode = dbo.sp_MScreate_sub_tables IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) -- If no entry in MSsubscription_properties for this publication, add one. IF NOT EXISTS (select * from MSsubscription_properties where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication) BEGIN -- Use status rpc for local publisher, see bug 39385 declare @security_mode int declare @login sysname if UPPER(@@servername) = UPPER(@publisher) begin select @security_mode = 2 end else begin select @security_mode = 0 select @login = 'sa' end exec @retcode = dbo.sp_link_publication @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @security_mode = @security_mode, @login = @login, @password = NULL IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) END if exists (select * from sysobjects where replinfo & @merge_pub_object_bit <> 0 and id = @object_id) begin raiserror(21063, 16, 1, @qualname) return (1) end /* ** Create system table MSreplication_objects if it does not exist */ IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND name = 'MSreplication_objects') BEGIN CREATE TABLE dbo.MSreplication_objects ( publisher sysname NULL, publisher_db sysname NULL, publication sysname NULL, object_name sysname NOT NULL, object_type char(2) NOT NULL ) IF @@ERROR <> 0 begin rollback transaction return (1) end EXEC dbo.sp_MS_marksystemobject 'MSreplication_objects' CREATE UNIQUE CLUSTERED INDEX ucMSreplication_objects ON dbo.MSreplication_objects(object_name) IF @@ERROR <> 0 begin rollback transaction return (1) end END -- Drop all replication triggers on the source object -- We should drop all because we don't support updatable subscriptions to -- multiple publications on same dest table. declare object_cursor CURSOR LOCAL FAST_FORWARD for select o.object_name, so.id from MSreplication_objects o, sysobjects so where o.object_name = so.name and so.parent_obj = @object_id and o.object_type = 'T' declare @old_id int declare @old_name sysname OPEN object_cursor FETCH object_cursor INTO @old_name, @old_id WHILE (@@fetch_status <> -1) BEGIN exec @retcode = dbo.sp_MSdrop_object @object_id = @old_id if @retcode <> 0 or @@error <> 0 goto UNDO delete from MSreplication_objects where object_name=@old_name FETCH object_cursor INTO @old_name, @old_id END CLOSE object_cursor DEALLOCATE object_cursor -- Generate trigger names select @trigname = RTRIM(SUBSTRING(@sub_table,1,110)) select @ins_trig = N'trg_MSsync_ins_' + @trigname select @upd_trig = N'trg_MSsync_upd_' + @trigname select @del_trig = N'trg_MSsync_del_' + @trigname -- check uniqueness of names and revert to ugly guid-based name if friendly name already exists if exists (select name from sysobjects where name in (@ins_trig, @upd_trig, @del_trig)) begin declare @guid_name nvarchar(36) select @guid_name = convert (nvarchar(36), newid()) select @ins_trig = 'trg_MSsync_ins_' + @guid_name select @upd_trig = 'trg_MSsync_upd_' + @guid_name select @del_trig = 'trg_MSsync_del_' + @guid_name end exec @retcode = master..xp_varbintohexstr @primary_key_bitmap, @bitmap_str output if @retcode <> 0 or @@error <> 0 return 1 /* exec ('if exists (select * from sysobjects where name = N''' + @ins_trig + N''' and xtype = N''TR'') drop trigger ' + @ins_trig) exec ('if exists (select * from sysobjects where name = N''' + @upd_trig + N''' and xtype = N''TR'') drop trigger ' + @upd_trig) exec ('if exists (select * from sysobjects where name = N''' + @del_trig + N''' and xtype = N''TR'') drop trigger ' + @del_trig) */ -- We are now going to create triggers, so start a transaction begin tran -- Call out to individual create trigger routines select @dbname = db_name() select @cmd = 'sp_MSscript_sync_ins_trig ' + convert( nvarchar, @object_id ) + ', ' + quotename(@publisher) + ', ' + quotename(@publisher_db) + ', ' + quotename(@ins_trig) + ', ' + quotename(@ins_proc) + ', ' + quotename(@proc_owner) + ', ' + quotename(@identity_col) + ', ' + quotename(@ts_col) if @filter_clause in ('NULL', 'null') select @cmd = @cmd + ', null' else select @cmd = @cmd + ', N''' + replace (@filter_clause,'''','''''') + '''' exec master..xp_execresultset @cmd, @dbname IF @@ERROR <> 0 goto UNDO select @cmd = 'sp_MSscript_sync_upd_trig ' + convert( nvarchar, @object_id ) + ', ' + quotename(@publisher) + ', ' + quotename(@publisher_db) + ', ' + quotename(@upd_trig) + ', ' + quotename(@upd_proc) + ', ' + quotename(@proc_owner) + ', ' + quotename(@identity_col) + ', ' + quotename(@ts_col) if @filter_clause in ('NULL', 'null') select @cmd = @cmd + ', null' else select @cmd = @cmd + ', N''' + replace (@filter_clause,'''','''''') + '''' -- Update need primary key bitmap select @cmd = @cmd + ', ' + @bitmap_str exec master..xp_execresultset @cmd, @dbname IF @@ERROR <> 0 goto UNDO select @cmd = 'sp_MSscript_sync_del_trig ' + convert( nvarchar, @object_id ) + ', ' + quotename(@publisher) + ', ' + quotename(@publisher_db) + ', ' + quotename(@del_trig) + ', ' + quotename(@del_proc) + ', ' + quotename(@proc_owner) + ', ' + quotename(@identity_col) + ', ' + quotename(@ts_col) if @filter_clause in ('NULL', 'null') select @cmd = @cmd + ', null' else select @cmd = @cmd + ', N''' + replace (@filter_clause,'''','''''') + '''' -- Delete need primary key bitmap select @cmd = @cmd + ', ' + @bitmap_str exec master..xp_execresultset @cmd, @dbname IF @@ERROR <> 0 goto UNDO -- Drop old entries before insert. The triggers with those names -- are created as above. delete MSreplication_objects where object_name = @ins_trig IF @@ERROR <> 0 goto UNDO delete MSreplication_objects where object_name = @upd_trig IF @@ERROR <> 0 goto UNDO delete MSreplication_objects where object_name = @del_trig IF @@ERROR <> 0 goto UNDO -- Mark procedures as system procs so they don't show up in the UI select @cmd = 'exec dbo.sp_MS_marksystemobject ' + quotename(@ins_trig) exec (@cmd) IF @@ERROR <> 0 goto UNDO insert into MSreplication_objects(publisher, publisher_db, publication, object_name, object_type) values(@publisher, @publisher_db, @publication, @ins_trig, 'T') IF @@ERROR <> 0 goto UNDO select @cmd = 'exec dbo.sp_MS_marksystemobject ' + quotename(@upd_trig) exec (@cmd) IF @@ERROR <> 0 goto UNDO insert into MSreplication_objects(publisher, publisher_db, publication, object_name, object_type) values(@publisher, @publisher_db, @publication, @upd_trig, 'T') IF @@ERROR <> 0 goto UNDO select @cmd = 'exec dbo.sp_MS_marksystemobject ' + quotename(@del_trig) exec (@cmd) IF @@ERROR <> 0 goto UNDO insert into MSreplication_objects(publisher, publisher_db, publication, object_name, object_type) values(@publisher, @publisher_db, @publication, @del_trig, 'T') IF @@ERROR <> 0 goto UNDO -- Mark the table for warnings in BCP update sysobjects set replinfo = replinfo | @synctran_bit where id = @object_id -- commit tran commit tran return (0) UNDO: if @@trancount <> 0 rollback tran return(1) go grant exec on dbo.sp_addsynctriggers to public go -------------------------------------------------------------------------------- --. sp_MScheck_agent_instance -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MScheck_agent_instance') drop procedure sp_MScheck_agent_instance go raiserror('Creating procedure sp_MScheck_agent_instance', 0,1) GO CREATE PROCEDURE sp_MScheck_agent_instance @application_name sysname, @agent_type int = NULL as declare @count_pro int set nocount on select @count_pro = count(*) from master..sysprocesses where program_name = @application_name if @agent_type = 3 begin -- The distribution agent will before connecting to the publisher with unique -- application name if @count_pro > 0 raiserror (21036, 16, -1, 'distribution') end else if @agent_type = 4 begin -- The merge agent will connect to the publisher with unique application name -- then call this procedure if @count_pro > 1 raiserror (21036, 16, -1, 'merge') end else if @agent_type = 1 begin -- The snapshot agent will connect to the distributiondb with unique application name -- then call this procedure if @count_pro > 2 raiserror (21036, 16, -1, 'snapshot') end else if @agent_type = 2 begin -- The logreader agent will connect to the distributiondb with unique application name -- then call this procedure if @count_pro > 1 raiserror (21036, 16, -1, 'logreader') end go grant exec on dbo.sp_MScheck_agent_instance to public go -------------------------------------------------------------------------------- --. sp_MSCleanupForPullReinit -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSCleanupForPullReinit') drop procedure sp_MSCleanupForPullReinit go raiserror('Creating procedure sp_MSCleanupForPullReinit', 0,1) GO CREATE PROCEDURE sp_MSCleanupForPullReinit ( @publication sysname, @publisher_db sysname, @publisher sysname = @@servername ) AS declare @pubid uniqueidentifier declare @parentid uniqueidentifier declare @artid uniqueidentifier declare @retcode smallint /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) /* This only gets called after database is enable to subscribe, so sysmergepublications should exist */ select @pubid = pubid, @parentid = parentid FROM sysmergepublications WHERE name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db = @publisher_db /* Normal case - nothing to cleanup, just return */ if @pubid is null return (1) delete from MSmerge_genhistory where pubid = @pubid delete from sysmergesubsetfilters where pubid=@pubid delete from sysmergeschemachange where pubid = @pubid delete from MSmerge_contents where tablenick in (select nickname from sysmergearticles where pubid=@pubid) delete from MSmerge_tombstone where tablenick in (select nickname from sysmergearticles where pubid=@pubid) GO grant execute on dbo.sp_MSCleanupForPullReinit to public go -- BUGBUG : sp_MSCleanupForPullReinit doesn't follow naming standard -------------------------------------------------------------------------------- --. sp_MSpublicationcleanup -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSpublicationcleanup') drop procedure sp_MSpublicationcleanup go raiserror('Creating procedure sp_MSpublicationcleanup', 0,1) GO CREATE PROCEDURE sp_MSpublicationcleanup ( @publication sysname, @publisher_db sysname, @publisher sysname = @@servername ) AS declare @pubid uniqueidentifier declare @parentid uniqueidentifier declare @artid uniqueidentifier declare @retcode smallint /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) /* This only gets called after database is enable to subscribe, so sysmergepublications should exist */ select @pubid = pubid, @parentid = parentid FROM sysmergepublications WHERE name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db = @publisher_db /* Normal case - nothing to cleanup, just return */ if @pubid is null return (1) /* Clean up the articles for this publication, and delete the row */ select @artid = artid FROM sysmergearticles WHERE pubid = @pubid while @artid is not null begin if not exists (select * from sysmergearticles WHERE artid = @artid and pubid <> @pubid) begin exec @retcode=sp_MSarticlecleanup @pubid, @artid if @retcode<>0 or @@ERROR<>0 return (1) end delete from sysmergearticles where artid = @artid and pubid = @pubid set @artid = NULL select @artid = artid FROM sysmergearticles WHERE pubid = @pubid end /* Now clean up any traces in other system tables */ delete from MSmerge_genhistory where pubid = @pubid delete from MSmerge_replinfo where repid in (select subid from sysmergesubscriptions where pubid = @pubid and status <> 2) delete from sysmergesubsetfilters where pubid=@pubid delete from sysmergesubscriptions where pubid = @pubid and status <> 2 delete from sysmergepublications where pubid = @pubid delete from sysmergeschemachange where pubid = @pubid GO grant execute on dbo.sp_MSpublicationcleanup to public go -------------------------------------------------------------------------------- --. sp_MSarticlecleanup -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSarticlecleanup') drop procedure sp_MSarticlecleanup go raiserror('Creating procedure sp_MSarticlecleanup', 0,1) GO create procedure sp_MSarticlecleanup (@pubid uniqueidentifier, @artid uniqueidentifier) as set nocount on declare @source_table nvarchar(258) declare @conflict_table nvarchar(258) declare @ownername sysname declare @objectname sysname declare @tablenick int declare @objid int declare @sync_objid int declare @view_type int declare @tsview nvarchar(50) declare @guidstr nvarchar(50) declare @csview nvarchar(50) declare @viewname nvarchar(258) declare @retcode smallint declare @qualified_name nvarchar(258) declare @bi_tablename sysname declare @bi_viewname sysname declare @bi_procname sysname -- to be called after article is set up in a subscriber /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 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 -- construct the qualified table name select @source_table = @ownername + '.' + @objectname exec @retcode=sp_MSguidtostr @artid, @guidstr out if @retcode<>0 or @@ERROR<>0 return (1) -- get the insert, update and conflict proc names from sysmergearticles select @sync_objid = sync_objid, @view_type = view_type, @tablenick = nickname, @bi_tablename = object_name(before_image_objid), @bi_viewname = object_name(before_view_objid), @conflict_table = conflict_table from sysmergearticles where pubid = @pubid and artid = @artid /* ** We are not owner_qualifed this conflict table because it is created by snapshot agent */ select @qualified_name = QUOTENAME(@conflict_table) /* Drop the conflict table */ if (@conflict_table IS NOT NULL) and exists (select * from sysobjects where name = @conflict_table and type = 'U') begin exec ('drop table ' + @qualified_name) if @@ERROR<>0 return (1) end select @qualified_name = QUOTENAME(@ownername) + '.' + QUOTENAME(@conflict_table) /* If there is a before image table, drop it and its cleanup proc */ if (@bi_tablename is not null) begin set @bi_procname = @bi_tablename + '_clean' if exists (select * from sysobjects where name = @bi_procname and type = 'P') begin exec ('drop proc ' + @bi_procname) if @@ERROR<>0 return (1) end exec ('drop table ' + @bi_tablename) if @@ERROR<>0 return (1) end /* If there is a before image view, drop it */ if (@bi_viewname is not null) begin exec ('drop view ' + @bi_viewname) if @@ERROR<>0 return (1) end /* Drop the article procs */ exec @retcode=sp_MSdroparticleprocs @pubid, @artid if @@ERROR<>0 or @retcode<>0 return (1) /* Drop the article triggers */ exec @retcode=sp_MSdroparticletriggers @source_table if @@ERROR<>0 or @retcode<>0 return (1) exec @retcode=sp_MSunmarkreplinfo @objectname, @ownername if @@ERROR<>0 or @retcode<>0 return (1) /* 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 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 select @ownername = user_name(uid) from sysobjects where name=@viewname set @viewname = QUOTENAME(@ownername) + '.' + QUOTENAME(@viewname) exec ('drop view ' + @viewname) if @@ERROR<>0 return (1) end end /* ** Drop the views created for MSmerge_contents and MSmerge_tombstone before dropping these two tables */ set @csview = 'ctsv_' + @guidstr set @tsview = 'tsvw_' + @guidstr if EXISTS (select * from sysobjects where name=@csview and type='V') BEGIN select @ownername = user_name(uid) from sysobjects where name=@csview select @viewname = QUOTENAME(@ownername) + '.' + QUOTENAME(@csview) exec ('drop view ' + @viewname) if @@ERROR<>0 return (1) END if EXISTS (select * from sysobjects where name=@tsview and type='V') BEGIN select @ownername = user_name(uid) from sysobjects where name=@tsview select @viewname = QUOTENAME(@ownername) + '.' + QUOTENAME(@tsview) exec ('drop view ' + @viewname) if @@ERROR<>0 return (1) END /* Delete from contents, tombstone, delete conflicts */ delete from MSmerge_contents where tablenick = @tablenick delete from MSmerge_tombstone where tablenick = @tablenick delete from MSmerge_delete_conflicts where tablenick = @tablenick GO grant execute on dbo.sp_MSarticlecleanup to public go -------------------------------------------------------------------------------- --. sp_subscription_cleanup -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_subscription_cleanup') drop procedure sp_subscription_cleanup go raiserror('Creating procedure sp_subscription_cleanup', 0,1) GO CREATE PROCEDURE sp_subscription_cleanup ( @publisher sysname, @publisher_db sysname, @publication sysname = NULL, @reserved nvarchar(10) = NULL )AS declare @object_name sysname declare @object_type char(2) declare @independent_agent bit declare @retcode int declare @synctran_bit int declare @parent_obj int declare @object_id int select @synctran_bit = 256 /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) if @publication = '' OR @publication is NULL select @independent_agent = 0 else select @independent_agent = 1 IF exists (select name from sysobjects where name = 'MSreplication_objects') BEGIN declare object_cursor CURSOR LOCAL FAST_FORWARD for select DISTINCT object_name, object_type from MSreplication_objects o where (UPPER(o.publisher) = UPPER(@publisher) and o.publisher_db = @publisher_db and o.publication = @publication) or @reserved = 'drop_all' OPEN object_cursor FETCH object_cursor INTO @object_name, @object_type WHILE (@@fetch_status <> -1) BEGIN IF @object_type = 'T' begin select @parent_obj = NULL select @parent_obj = parent_obj, @object_id = id from sysobjects where name = @object_name if @parent_obj is not null begin -- Unmark synctran bit update sysobjects set replinfo = replinfo & ~@synctran_bit where id = @parent_obj and (replinfo & @synctran_bit) <> 0 IF @@ERROR <> 0 GOTO UNDO exec @retcode = dbo.sp_MSdrop_object @object_id = @object_id if @retcode <> 0 or @@error <> 0 goto UNDO end end delete from MSreplication_objects where object_name=@object_name FETCH object_cursor INTO @object_name, @object_type END CLOSE object_cursor DEALLOCATE object_cursor if not exists (select * from MSreplication_objects) drop table MSreplication_objects END IF exists (select name from sysobjects where name = 'MSreplication_subscriptions') BEGIN delete from MSreplication_subscriptions where (UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND (@independent_agent=0 or publication = @publication)) or @reserved = 'drop_all' END IF EXISTS(select * from sysobjects where type='U' and name = 'MSsubscription_properties') BEGIN DELETE FROM MSsubscription_properties WHERE (UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication) or @reserved = 'drop_all' IF @@ERROR <> 0 GOTO UNDO IF NOT EXISTS (SELECT * FROM MSsubscription_properties) BEGIN DROP TABLE MSsubscription_properties IF @@ERROR <> 0 GOTO UNDO END END return (0) UNDO: return(1) GO -------------------------------------------------------------------------------- --. sp_vupgrade_subscription_database -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_vupgrade_subscription_databases') drop procedure sp_vupgrade_subscription_databases go raiserror('Creating procedure sp_vupgrade_subscription_databases', 0,1) GO create procedure sp_vupgrade_subscription_databases as declare @dbname sysname declare current_db CURSOR LOCAL FAST_FORWARD for select quotename(name) from master..sysdatabases for read only -- Note: dbname is quoted! open current_db fetch current_db into @dbname while ( @@fetch_status <> -1 ) begin exec ('use '+ @dbname + ' exec dbo.sp_vupgrade_mergetables') if @@ERROR<>0 begin close DC deallocate DC return (1) end exec ('use '+ @dbname + ' exec dbo.sp_vupgrade_subscription_tables') if @@ERROR<>0 begin close DC deallocate DC return (1) end fetch next from current_db into @dbname end close current_db deallocate current_db go -------------------------------------------------------------------------------- --. sp_vupgrade_subscription_tables -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_vupgrade_subscription_tables') drop procedure sp_vupgrade_subscription_tables go raiserror('Creating procedure sp_vupgrade_subscription_tables', 0,1) GO create procedure sp_vupgrade_subscription_tables as -- this raiserror makes sp_vupgrade_replication.out file easier to read raiserror('sp_vupgrade_subscription_tables', 0,1) DECLARE @table_name sysname -- Create unique index on tables that did not have one previously. The index is not created -- if duplicates rows exist in the table. -- MSreplication_subscriptions SELECT @table_name = N'MSreplication_subscriptions' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSreplication_subscriptions' ) BEGIN IF EXISTS ( SELECT publication, publisher_db, publisher, subscription_type FROM MSreplication_subscriptions GROUP BY publication, publisher_db, publisher, subscription_type HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 1, @table_name) ELSE IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'uc1MSReplication_subscriptions' AND id = OBJECT_ID('MSreplication_subscriptions') ) CREATE UNIQUE CLUSTERED INDEX uc1MSReplication_subscriptions ON MSreplication_subscriptions(publication, publisher_db, publisher, subscription_type) END -- MSsubscription_properties SELECT @table_name = N'MSsubscription_properties' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSsubscription_properties' ) BEGIN IF EXISTS ( SELECT publication, publisher_db, publisher FROM MSsubscription_properties GROUP BY publication, publisher_db, publisher HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 2, @table_name) ELSE IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'uc1MSsubscription_properties' AND id = OBJECT_ID('MSsubscription_properties') ) CREATE UNIQUE CLUSTERED INDEX uc1MSsubscription_properties ON MSsubscription_properties(publication, publisher_db, publisher) END -- MSreplication_objects SELECT @table_name = N'MSreplication_objects' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSreplication_objects' ) BEGIN IF EXISTS ( SELECT object_name FROM MSreplication_objects GROUP BY object_name HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 3, @table_name) ELSE IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'ucMSreplication_objects' AND id = OBJECT_ID('MSreplication_objects') ) CREATE UNIQUE CLUSTERED INDEX ucMSreplication_objects ON dbo.MSreplication_objects(object_name) END go -------------------------------------------------------------------------------- --. sp_vupgrade_mergetables -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_vupgrade_mergetables') drop procedure sp_vupgrade_mergetables go raiserror('Creating procedure sp_vupgrade_mergetables', 0,1) GO create procedure sp_vupgrade_mergetables as -- this raiserror makes sp_vupgrade_replication.out file easier to read raiserror('sp_vupgrade_mergetables', 0,1) DECLARE @table_name sysname if (exists (select * from sysobjects where name = 'sysmergearticles')) begin -- Columns have been added to the sysmergearticles table if not exists (select * from syscolumns where id = object_id('sysmergearticles') and name = 'gen_cur') begin alter table sysmergearticles add gen_cur int null if @@ERROR <> 0 return 1 end if not exists (select * from syscolumns where id = object_id('sysmergearticles') and name = 'before_image_objid') begin alter table sysmergearticles add before_image_objid int NULL if @@ERROR <> 0 return 1 end if not exists (select * from syscolumns where id = object_id('sysmergearticles') and name = 'before_view_objid') begin alter table sysmergearticles add before_view_objid int NULL if @@ERROR <> 0 return 1 end end -- MSmerge_contents SELECT @table_name = N'MSmerge_contents' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSmerge_contents' ) BEGIN IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'nc3MSmerge_contents' AND id = OBJECT_ID('MSmerge_contents') ) create index nc3MSmerge_contents on MSmerge_contents(tablenick, partchangegen) IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'nc4MSmerge_contents' AND id = OBJECT_ID('MSmerge_contents') ) create index nc4MSmerge_contents on MSmerge_contents(generation, partchangegen) END -- sysmergepublications SELECT @table_name = N'sysmergepublications' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'sysmergepublications' ) BEGIN if not exists (select * from syscolumns where id = object_id('sysmergepublications') and name = 'keep_before_values') begin alter table sysmergepublications add keep_before_values int null if @@ERROR <> 0 return 1 end IF EXISTS ( SELECT pubid FROM sysmergepublications GROUP BY pubid HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 4, @table_name) ELSE IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'nc1sysmergepublications' AND id = OBJECT_ID('sysmergepublications') ) CREATE UNIQUE NONCLUSTERED INDEX nc1sysmergepublications ON sysmergepublications(pubid) END -- MSmerge_genhistory SELECT @table_name = N'MSmerge_genhistory' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSmerge_genhistory' ) BEGIN -- Only create the index index if guidsrc values are unique. Before SP1 it was possible -- for this table to contain dup guidsrc. This happened when the genhistory table was empty to start -- and we insert an initial row (for no article) and then try to insert a row for the first -- article without generating a new guid. IF EXISTS ( SELECT guidsrc, pubid FROM MSmerge_genhistory GROUP BY guidsrc, pubid HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 5, @table_name) ELSE IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'nc3MSmerge_genhistory' AND id = OBJECT_ID('MSmerge_genhistory') ) CREATE UNIQUE NONCLUSTERED INDEX nc3MSmerge_genhistory ON MSmerge_genhistory(guidsrc, pubid) IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'nc4MSmerge_genhistory' AND id = OBJECT_ID('MSmerge_genhistory') ) create index nc4MSmerge_genhistory on MSmerge_genhistory(coldate) END -- MSmerge_delete_conflicts SELECT @table_name = N'MSmerge_delete_conflicts' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSmerge_delete_conflicts' ) BEGIN IF EXISTS ( SELECT tablenick, rowguid, origin_datasource FROM MSmerge_delete_conflicts GROUP BY tablenick, rowguid, origin_datasource HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 6, @table_name) ELSE IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'nc1MSmerge_delete_conflicts' AND id = OBJECT_ID('MSmerge_delete_conflicts') ) CREATE UNIQUE NONCLUSTERED INDEX nc1MSmerge_delete_conflicts ON MSmerge_delete_conflicts(tablenick, rowguid, origin_datasource) END -- sysmergeschemachange SELECT @table_name = N'sysmergeschemachange' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'sysmergeschemachange' ) BEGIN IF EXISTS ( SELECT schemaversion, pubid FROM sysmergeschemachange GROUP BY schemaversion, pubid HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 7, @table_name) ELSE BEGIN IF EXISTS ( SELECT * FROM sysindexes WHERE name = 'schemachangeversion' AND id = OBJECT_ID('sysmergeschemachange') ) DROP INDEX sysmergeschemachange.schemachangeversion -- Recreate this index as unique clustered with one more field in index key. CREATE UNIQUE CLUSTERED INDEX schemachangeversion ON sysmergeschemachange(schemaversion, pubid) END END -- sysmergesubsetfilters SELECT @table_name = N'sysmergesubsetfilters' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'sysmergesubsetfilters' ) BEGIN IF EXISTS ( SELECT join_filterid FROM sysmergesubsetfilters GROUP BY join_filterid HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 8, @table_name) ELSE IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'nc1sysmergesubsetfilters' AND id = OBJECT_ID('sysmergesubsetfilters') ) CREATE UNIQUE NONCLUSTERED INDEX nc1sysmergesubsetfilters ON sysmergesubsetfilters(join_filterid, pubid) END IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'sysmergepublications' ) BEGIN declare @artname sysname declare @pubname sysname declare @retcode int -- Must recreate the article procs for all articles that already have a select proc declare cur_articles CURSOR LOCAL FAST_FORWARD for select a.name, p.name from sysmergearticles a, sysmergepublications p where a.select_proc is not null and a.pubid = p.pubid for read only open cur_articles fetch cur_articles into @artname, @pubname while ( @@fetch_status <> -1 ) begin exec @retcode = sp_MSsetartprocs @publication = @pubname, @article = @artname, @force_flag = 1 if @@ERROR <>0 OR @retcode <>0 return (1) fetch cur_articles into @artname, @pubname end close cur_articles deallocate cur_articles END GO -------------------------------------------------------------------------------- --. sp_vupgrade_replication -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_vupgrade_replication') drop procedure sp_vupgrade_replication go raiserror('Creating procedure sp_vupgrade_replication', 0,1) GO create procedure sp_vupgrade_replication ( @login sysname = N'sa', @password sysname = N'', @ver_old int = 623, @security_mode bit = 0 ) as -- this raiserror makes sp_vupgrade_replication.out file easier to read raiserror('sp_vupgrade_replication', 0,1) begin /* * Stub to handle possible need to modify or supplement replication metadata during setup * initiated version upgrade from RTM to SP1. Any schema changes * to replication system tables may require modifications here to maintain upgrade path. * * If server is a distributor, run new instdist.sql against all distribution dbs. * If version upgraded from is pre-Beta 3 OR @force_remove is true, do hard strip of replication. * * This proc gets called by setup at the end of an install over an existing version. */ set nocount on declare @dbname sysname declare @install_path nvarchar(255) declare @osql_cmd nvarchar(512) declare @osql_for_nt int declare @retcode int declare @platform_nt binary -- db bits declare @db_distbit int select @db_distbit = 16 -- version check declare @ver_min int select @platform_nt = 0x1 select @ver_min= 623 -- check for @ver_old < @ver_min and bailout if true. Should not even get -- here since setup should have detected this earlier if ( @ver_old < @ver_min ) return(1) else begin -- always need to run instdist.sql to update distribution databases on a distributor -- setup must restart in non-single user mode so we can shell out to run instdist.sql scripts if exists( select * from master..sysdatabases where category & @db_distbit = @db_distbit ) begin -- get install_path exec @retcode = master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\Setup', 'SQLPath', @param = @install_path OUTPUT if ( @retcode <> 0 ) or ( @install_path is null ) or ( @install_path = N'' ) begin return(1) end -- Set the flag for platform if (( platform() & @platform_nt = @platform_nt )) select @osql_for_nt = 1 else select @osql_for_nt = 0 declare cur_distdb CURSOR LOCAL FAST_FORWARD for select name from master..sysdatabases where category & @db_distbit = @db_distbit for read only open cur_distdb fetch cur_distdb into @dbname while ( @@fetch_status <> -1 ) begin /* * Format osql cmd line appropriate for security mode and OS to run instdist.sql against * each distribution database. Instdist.sql will recompile procs and will also do some * schema and metadata upgrade of changed replication tables. Query timeout increased to * make enough time for alter tables in instdist.sql run for upgrade to complete. */ if (@osql_for_nt = 1) select @osql_cmd = '" "' else select @osql_cmd = ' "' -- Cannot specify -S w/ -E for local execution, SID does not map (nofix) if ( @security_mode = 1 and @osql_for_nt = 1 ) select @osql_cmd = @osql_cmd + @install_path + '\binn\osql" -E ' else select @osql_cmd = @osql_cmd + @install_path + '\binn\osql" -U' + isnull(@login, N'sa') + ' -P' + isnull(@password, N'') + ' -S' + @@SERVERNAME select @osql_cmd = @osql_cmd + ' -l30 -t30 ' select @osql_cmd = @osql_cmd + ' -b ' + ' -d' + @dbname select @osql_cmd = @osql_cmd + ' -i' + '"' + @install_path + '\install\instdist.sql"' + ' -o' + '"' + @install_path + '\install\instdist.out"' if (@osql_for_nt = 1) select @osql_cmd = @osql_cmd + ' "' exec @retcode = master..xp_cmdshell @osql_cmd if @retcode <> 0 or @@error <> 0 begin raiserror (14113, 16, -1, @osql_cmd, 'instdist.out') end -- now add unique indexes in this distribution database exec ('use '+ @dbname + ' exec dbo.sp_vupgrade_distdb') if @@error <> 0 return(1) fetch next from cur_distdb into @dbname end close cur_distdb deallocate cur_distdb -- Upgrade replication settings/tables in MSDB database -- ONLY FOR DISTRIBUTORS exec @retcode = msdb.dbo.sp_vupgrade_replmsdb if @retcode <> 0 or @@error <> 0 return (1) end -- Note: place calls to procs for any schema or metadata changes required in else block here -- Update subscription database schema. This will upgrade tran subscriber changes as well as ALL merge system tables -- As of 1/26/99 there are no changes needed for tran publisher tables exec @retcode = dbo.sp_vupgrade_subscription_databases if @retcode <> 0 or @@error <> 0 return (1) end return (0) end go -------------------------------------------------------------------------------- --. sp_vupgrade_distdb -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_vupgrade_distdb') drop procedure sp_vupgrade_distdb go raiserror('Creating procedure sp_vupgrade_distdb', 0,1) go create procedure sp_vupgrade_distdb as /* ** used to upgrade replication settings/tables in each distribution database */ -- this raiserror makes sp_vupgrade_replication.out file easier to read raiserror('sp_vupgrade_distdb', 0,1) DECLARE @table_name sysname -- MSrepl_version SELECT @table_name = N'MSrepl_version' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSrepl_version' ) BEGIN IF EXISTS ( SELECT major_version, minor_version, revision FROM MSrepl_version GROUP BY major_version, minor_version, revision HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 9, @table_name) ELSE IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'ucMSrepl_version' AND id = OBJECT_ID('MSrepl_version') ) CREATE UNIQUE CLUSTERED INDEX ucMSrepl_version ON dbo.MSrepl_version (major_version, minor_version, revision) END -- MSsnapshot_history SELECT @table_name = N'MSsnapshot_history' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSsnapshot_history' ) BEGIN IF EXISTS ( SELECT agent_id, timestamp, start_time, time FROM MSsnapshot_history GROUP BY agent_id, timestamp, start_time, time HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 10, @table_name) ELSE IF EXISTS ( SELECT * FROM sysindexes WHERE name = 'ucMSsnapshot_history' AND id = OBJECT_ID('MSsnapshot_history')) BEGIN DROP INDEX dbo.MSsnapshot_history.ucMSsnapshot_history CREATE UNIQUE CLUSTERED INDEX ucMSsnapshot_history ON dbo.MSsnapshot_history (agent_id, timestamp, start_time, time) END END -- MSlogreader_history SELECT @table_name = N'MSlogreader_history' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSlogreader_history' ) BEGIN IF EXISTS ( SELECT agent_id, timestamp, runstatus, start_time, time FROM MSlogreader_history GROUP BY agent_id, timestamp, runstatus, start_time, time HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 11, @table_name) ELSE IF EXISTS ( SELECT * FROM sysindexes WHERE name = 'ucMSlogreader_history' AND id = OBJECT_ID('MSlogreader_history')) BEGIN DROP INDEX dbo.MSlogreader_history.ucMSlogreader_history CREATE UNIQUE CLUSTERED INDEX ucMSlogreader_history ON dbo.MSlogreader_history (agent_id, timestamp, runstatus, start_time, time) END END -- MSdistribution_history SELECT @table_name = N'MSdistribution_history' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSdistribution_history' ) BEGIN IF EXISTS ( SELECT agent_id, timestamp, runstatus, start_time, time FROM MSdistribution_history GROUP BY agent_id, timestamp, runstatus, start_time, time HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 12, @table_name) ELSE IF EXISTS ( SELECT * FROM sysindexes WHERE name = 'ucMSdistribution_history' AND id = OBJECT_ID('MSdistribution_history')) BEGIN DROP INDEX dbo.MSdistribution_history.ucMSdistribution_history CREATE UNIQUE CLUSTERED INDEX ucMSdistribution_history ON dbo.MSdistribution_history (agent_id, timestamp, runstatus, start_time, time) END END -- MSmerge_history SELECT @table_name = N'MSmerge_history' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSmerge_history' ) BEGIN IF EXISTS ( SELECT agent_id, timestamp, runstatus, start_time, time FROM MSmerge_history GROUP BY agent_id, timestamp, runstatus, start_time, time HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 13, @table_name) ELSE IF EXISTS ( SELECT * FROM sysindexes WHERE name = 'ucMSmerge_history' AND id = OBJECT_ID('MSmerge_history')) BEGIN DROP INDEX dbo.MSmerge_history.ucMSmerge_history CREATE UNIQUE CLUSTERED INDEX ucMSmerge_history ON dbo.MSmerge_history (agent_id, timestamp, runstatus, start_time, time) END END -- MSsnapshot_agents SELECT @table_name = N'MSsnapshot_agents' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSsnapshot_agents' ) BEGIN IF EXISTS ( SELECT id FROM MSsnapshot_agents GROUP BY id HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 14, @table_name) ELSE IF EXISTS ( SELECT * FROM sysindexes WHERE name = 'iMSsnapshot_agents' AND id = OBJECT_ID('MSsnapshot_agents')) BEGIN DROP INDEX dbo.MSsnapshot_agents.iMSsnapshot_agents CREATE UNIQUE INDEX iMSsnapshot_agents ON dbo.MSsnapshot_agents (id) END END -- MSlogreader_agents SELECT @table_name = N'MSlogreader_agents' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSlogreader_agents' ) BEGIN IF EXISTS ( SELECT id FROM MSlogreader_agents GROUP BY id HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 15, @table_name) ELSE IF EXISTS ( SELECT * FROM sysindexes WHERE name = 'iMSlogreader_agents' AND id = OBJECT_ID('MSlogreader_agents')) BEGIN DROP INDEX dbo.MSlogreader_agents.iMSlogreader_agents CREATE UNIQUE INDEX iMSlogreader_agents ON dbo.MSlogreader_agents (id) END END -- MSdistribution_agents SELECT @table_name = N'MSdistribution_agents' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSdistribution_agents' ) BEGIN IF EXISTS ( SELECT id FROM MSdistribution_agents GROUP BY id HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 16, @table_name) ELSE IF EXISTS ( SELECT * FROM sysindexes WHERE name = 'ucMSdistribution_agents' AND id = OBJECT_ID('MSdistribution_agents')) BEGIN DROP INDEX dbo.MSdistribution_agents.ucMSdistribution_agents CREATE UNIQUE CLUSTERED INDEX ucMSdistribution_agents ON dbo.MSdistribution_agents (id) END END -- MSmerge_agents SELECT @table_name = N'MSmerge_agents' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSmerge_agents' ) BEGIN IF EXISTS ( SELECT id FROM MSmerge_agents GROUP BY id HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 17, @table_name) ELSE IF EXISTS ( SELECT * FROM sysindexes WHERE name = 'iMSmerge_agents' AND id = OBJECT_ID('MSmerge_agents')) BEGIN DROP INDEX dbo.MSmerge_agents.iMSmerge_agents CREATE UNIQUE INDEX iMSmerge_agents ON dbo.MSmerge_agents (id) END END -- MSpublication_access SELECT @table_name = N'MSpublication_access' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSpublication_access' ) BEGIN IF EXISTS ( SELECT publication_id, login FROM MSpublication_access GROUP BY publication_id, login HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 18, @table_name) ELSE IF EXISTS ( SELECT * FROM sysindexes WHERE name = 'ucMSpublication_access' AND id = OBJECT_ID('MSpublication_access')) BEGIN DROP INDEX dbo.MSpublication_access.ucMSpublication_access CREATE UNIQUE CLUSTERED INDEX ucMSpublication_access ON dbo.MSpublication_access (publication_id, login) END END go -------------------------------------------------------------------------------- --. sp_vupgrade_replmsdb -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_vupgrade_replmsdb') drop procedure sp_vupgrade_replmsdb go raiserror('Creating procedure sp_vupgrade_replmsdb', 0,1) go create procedure sp_vupgrade_replmsdb as /* ** used to upgrade replication settings/tables in MSDB database */ -- this raiserror makes sp_vupgrade_replication.out file easier to read raiserror('sp_vupgrade_replmsdb', 0,1) DECLARE @table_name sysname -- MSdistpublishers SELECT @table_name = N'MSdistpublishers' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSdistpublishers' ) BEGIN IF EXISTS ( SELECT name FROM MSdistpublishers GROUP BY name HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 19, @table_name) ELSE IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'uc1MSdistpublishers' AND id = OBJECT_ID('MSdistpublishers') ) CREATE UNIQUE CLUSTERED INDEX uc1MSdistpublishers ON msdb.dbo.MSdistpublishers(name) END -- MSdistributiondbs SELECT @table_name = N'MSdistributiondbs' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSdistributiondbs' ) BEGIN IF EXISTS ( SELECT name FROM MSdistributiondbs GROUP BY name HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 20, @table_name) ELSE IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'uc1MSdistributiondbs' AND id = OBJECT_ID('MSdistributiondbs') ) CREATE UNIQUE CLUSTERED INDEX uc1MSdistributiondbs ON msdb.dbo.MSdistributiondbs(name) END -- MSdistributor SELECT @table_name = N'MSdistributor' IF EXISTS ( SELECT * FROM sysobjects WHERE name = 'MSdistributor' ) BEGIN IF EXISTS ( SELECT property FROM MSdistributor GROUP BY property HAVING COUNT(*) > 1 ) RAISERROR (21144, 10, 21, @table_name) ELSE IF NOT EXISTS ( SELECT * FROM sysindexes WHERE name = 'uc1MSdistributor' AND id = OBJECT_ID('MSdistributor') ) CREATE UNIQUE CLUSTERED INDEX uc1MSdistributor ON msdb.dbo.MSdistributor(property) END go -------------------------------------------------------------------------------- --. sp_restoredbreplication -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_restoredbreplication') drop procedure sp_restoredbreplication go raiserror('Creating procedure sp_restoredbreplication', 0,1) go create procedure sp_restoredbreplication ( @srv_orig sysname, @db_orig sysname ) as /* * used by restore process to strip out replication settings if restoring to non-originating * server/db or system otherwise not capable of keeping replication working * WARNING : procs called here run internal to server and must be owner qualified */ begin set nocount on -- db bits declare @db_tranbit int declare @db_mergbit int declare @db_distbit int select @db_tranbit = 1, @db_mergbit = 4, @db_distbit = 16 declare @repl_installed bit -- repl procs installed flag declare @remove_repl bit -- remove replication flag ; remove on true (1) declare @restoreoverride int declare @db_curr sysname DECLARE @retcode int DECLARE @proc nvarchar(255) -- Support override of replication remove on attach and restore select @proc = 'master.dbo.xp_regread ' execute @retcode = @proc 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\Replication', 'RestoreOverride', @param = @restoreoverride output, @no_output = 'no_output' if ( @@error = 0 ) and ( @retcode = 0 ) begin -- ReplRestoreOverride = 1 = user elects to take no cleanup on restore or attach if ( isnull( @restoreoverride, 0 ) = 1 ) return(0) end select @remove_repl = 0, @repl_installed = 1 select @db_curr = db_name() -- check server has replication installed; if not, we cannot remove replication; this should be benign if not exists ( select * from master..MSreplication_options where optname = 'transactional' or optname = 'merge' ) select @repl_installed = 0 -- check restore to same server/db backed up if ( UPPER(@srv_orig) <> UPPER(@@SERVERNAME) ) or ( @db_orig <> @db_curr ) select @remove_repl = 1 -- subscribing dbs are assumed ok -- distribution dbs are assumed ok -- publishing db check : transactional : requires coordinated restore of dist db - no way to check if ( exists( select * from sysobjects where name = 'syspublications' ) -- exists( select * from syspublications ) and not exists( select * from master..sysdatabases where name = @db_orig and category & @db_tranbit = @db_tranbit ) ) begin -- publications exist in db, but db on server is not published; -- unpublish the db, ignoring distributor cleanup update master.dbo.sysdatabases set category = category | @db_tranbit where name = @db_curr exec dbo.sp_MSpublishdb 'false', 1 update master.dbo.sysdatabases set category = category & ~@db_tranbit where name = @db_curr -- we've already brute force stripped replication from the db, -- don't call sp_removedbreplication at proc exit end if ( @repl_installed = 1 ) and ( @remove_repl = 1 ) exec dbo.sp_removedbreplication @db_curr end go -------------------------------------------------------------------------------- --. sp_MScreate_sub_tables -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MScreate_sub_tables') drop procedure sp_MScreate_sub_tables go raiserror('Creating procedure sp_MScreate_sub_tables', 0,1) GO CREATE PROCEDURE sp_MScreate_sub_tables ( @tran_sub_table bit = 0, @property_table bit = 1 ) as set nocount on declare @retcode int IF @tran_sub_table = 1 and (NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND name = 'MSreplication_subscriptions')) BEGIN CREATE TABLE dbo.MSreplication_subscriptions ( publisher sysname NOT NULL, publisher_db sysname NOT NULL, publication sysname NULL, independent_agent bit NOT NULL, subscription_type int NOT NULL, distribution_agent nvarchar (100) NULL, time smalldatetime NOT NULL, description nvarchar(255) NULL, transaction_timestamp varbinary(16) NOT NULL, -- SyncTran update_mode tinyint NOT NULL, agent_id binary(16) NULL, subscription_guid binary(16) NULL, subid binary(16) NULL, immediate_sync bit NOT NULL default 1 -- sync_mode with a default of 1 ) IF @@ERROR <> 0 GOTO UNDO CREATE UNIQUE CLUSTERED INDEX uc1MSReplication_subscriptions ON MSreplication_subscriptions(publication, publisher_db, publisher, subscription_type) IF @@ERROR <> 0 GOTO UNDO EXEC dbo.sp_MS_marksystemobject 'MSreplication_subscriptions' IF @@ERROR <> 0 GOTO UNDO END IF @property_table = 1 and NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND name = 'MSsubscription_properties') BEGIN BEGIN TRAN CREATE TABLE dbo.MSsubscription_properties ( publisher sysname NOT NULL, publisher_db sysname NOT NULL, publication sysname NOT NULL, publication_type int NOT NULL, publisher_login sysname NULL, publisher_password sysname NULL, publisher_security_mode int NOT NULL, distributor sysname NULL, distributor_login sysname NULL, distributor_password sysname NULL, distributor_security_mode int NOT NULL, ftp_address sysname NULL, ftp_port int NULL, ftp_login sysname NULL, ftp_password sysname NULL, ) IF @@ERROR <> 0 GOTO UNDO CREATE UNIQUE CLUSTERED INDEX uc1MSsubscription_properties ON MSsubscription_properties(publication, publisher_db, publisher) IF @@ERROR <> 0 GOTO UNDO EXEC @retcode = dbo.sp_MS_marksystemobject 'MSsubscription_properties' if @retcode <> 0 or @@error <> 0 GOTO UNDO COMMIT TRAN end return(0) UNDO: IF @@TRANCOUNT = 1 ROLLBACK TRAN ELSE COMMIT TRAN return(1) go grant execute on sp_MScreate_sub_tables to public go -------------------------------------------------------------------------------- --. sp_MSregistersubscription -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSregistersubscription') drop procedure sp_MSregistersubscription go raiserror('Creating procedure sp_MSregistersubscription', 0,1) go CREATE PROCEDURE sp_MSregistersubscription ( @replication_type int, /* Transactional = 1, Merge = 2 */ @publisher sysname, @publisher_db sysname, @publisher_security_mode int = NULL, /* 0 standard; 1 integrated */ @publisher_login sysname = NULL, @publisher_password sysname = NULL, @publication sysname, @subscriber sysname, @subscriber_db sysname, @subscriber_security_mode int = NULL, /* 0 standard; 1 integrated */ @subscriber_login sysname = NULL, @subscriber_password sysname = NULL, @distributor sysname, @distributor_security_mode int = NULL, @distributor_login sysname = NULL, @distributor_password sysname = NULL, @subscription_id uniqueidentifier , @independent_agent int = NULL, @subscription_type int ) AS SET NOCOUNT ON /* MobileSync Support */ declare @subscription_name nvarchar(1000) declare @regkey nvarchar(1000) declare @subidstr nvarchar(38) declare @profile_name nvarchar(100) declare @retcode int declare @publisher_encrypted_password sysname declare @subscriber_encrypted_password sysname declare @distributor_encrypted_password sysname declare @temp_binary_password varbinary(256) set @subscription_name = @publisher + ':' + @publisher_db + ':' + @publication + ':' + @subscriber + ':' + @subscriber_db /* Replace back slash with forward slash so that the key name is a valid REGISTRY key name */ set @subscription_name = REPLACE(@subscription_name,'\','/') set @regkey = 'SOFTWARE\Microsoft\MSSQLServer\Replication\Subscriptions\' + @subscription_name set @subidstr = '{' + convert ( nchar(36), @subscription_id) + '}' set @profile_name = formatmessage(20550) -- SyncMgr Profile EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'ProfileName', 'REG_SZ', @profile_name if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'ReplicationType', 'REG_DWORD', @replication_type if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'SubscriptionType', 'REG_DWORD', @subscription_type if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'Subid', 'REG_SZ', @subidstr if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'Publisher', 'REG_SZ', @publisher if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'PublisherDb', 'REG_SZ', @publisher_db if @retcode <> 0 OR @@ERROR <> 0 return 1 /* If Publisher security mode is NOT NULL, write out the entries */ if @publisher_security_mode IS NOT NULL begin EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'PublisherSecurityMode', 'REG_DWORD', @publisher_security_mode if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'PublisherLogin', 'REG_SZ', @publisher_login if @retcode <> 0 OR @@ERROR <> 0 return 1 /* Encrypt the password before writing to the registry */ set @publisher_encrypted_password = @publisher_password exec @retcode = master.dbo.xp_repl_encrypt @publisher_encrypted_password OUTPUT if @retcode <> 0 OR @@ERROR <> 0 return 1 select @temp_binary_password = convert(varbinary(256), @publisher_encrypted_password) EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'PublisherEncryptedPasswordBinary', 'REG_BINARY', @temp_binary_password if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'PublisherEncryptedPassword', 'REG_SZ', @publisher_encrypted_password if @retcode <> 0 OR @@ERROR <> 0 return 1 end EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'Publication', 'REG_SZ', @publication if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'Subscriber', 'REG_SZ', @subscriber if @retcode <> 0 OR @@ERROR <> 0 return 1 /* If Subscriber security mode is NOT NULL, write out the entries */ if @subscriber_security_mode IS NOT NULL begin EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'SubscriberSecurityMode', 'REG_DWORD', @subscriber_security_mode if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'SubscriberLogin', 'REG_SZ', @subscriber_login if @retcode <> 0 OR @@ERROR <> 0 return 1 /* Encrypt the password before writing to the registry */ set @subscriber_encrypted_password = @subscriber_password exec @retcode = master.dbo.xp_repl_encrypt @subscriber_encrypted_password OUTPUT if @retcode <> 0 OR @@ERROR <> 0 return 1 select @temp_binary_password = convert(varbinary(256), @subscriber_encrypted_password) EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'SubscriberEncryptedPasswordBinary', 'REG_BINARY', @temp_binary_password if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'SubscriberEncryptedPassword', 'REG_SZ', @subscriber_encrypted_password if @retcode <> 0 OR @@ERROR <> 0 return 1 end EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'SubscriberDb', 'REG_SZ', @subscriber_db if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'Distributor', 'REG_SZ', @distributor if @retcode <> 0 OR @@ERROR <> 0 return 1 /* If Distributor security mode is NOT NULL, write out the entries */ if @distributor_security_mode IS NOT NULL begin EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'DistributorSecurityMode', 'REG_DWORD', @distributor_security_mode if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'DistributorLogin', 'REG_SZ', @distributor_login if @retcode <> 0 OR @@ERROR <> 0 return 1 /* Encrypt the password before writing to the registry */ set @distributor_encrypted_password = @distributor_password exec @retcode = master.dbo.xp_repl_encrypt @distributor_encrypted_password OUTPUT if @retcode <> 0 OR @@ERROR <> 0 return 1 select @temp_binary_password = convert(varbinary(256), @distributor_encrypted_password) EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'DistributorEncryptedPasswordBinary', 'REG_BINARY', @temp_binary_password if @retcode <> 0 OR @@ERROR <> 0 return 1 EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'DistributorEncryptedPassword', 'REG_SZ', @distributor_encrypted_password if @retcode <> 0 OR @@ERROR <> 0 return 1 end if @independent_agent IS NOT NULL begin EXECUTE @retcode = master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', @regkey, 'IndependentAgent', 'REG_DWORD', @independent_agent if @retcode <> 0 OR @@ERROR <> 0 return 1 end return 0 GO -------------------------------------------------------------------------------- --. Common repl objects (replcom.sql) -------------------------------------------------------------------------------- dump tran master with no_log go -------------------------------------------------------------------------------- --. sp_MScreate_distributor_tables -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MScreate_distributor_tables') drop procedure sp_MScreate_distributor_tables go raiserror('Creating procedure sp_MScreate_distributor_tables', 0,1) GO create procedure sp_MScreate_distributor_tables as declare @profile_id int declare @retcode int declare @profile_name nvarchar(100) declare @profile_desc nvarchar(100) /* Create MSpublishers table */ IF EXISTS (SELECT * FROM msdb..sysobjects WHERE name = 'MSdistpublishers' and xtype = 'U') begin DROP TABLE msdb..MSdistpublishers if @@error<> 0 goto FAILURE end /* Create MSdistributiondbs table */ IF EXISTS (SELECT * FROM msdb..sysobjects WHERE name = 'MSdistributiondbs' and xtype = 'U') begin DROP TABLE msdb..MSdistributiondbs if @@error<> 0 goto FAILURE end /* create MSdistributor table */ IF EXISTS (SELECT * FROM msdb..sysobjects WHERE name = 'MSdistributor' and xtype = 'U') begin DROP TABLE msdb..MSdistributor if @@error<> 0 goto FAILURE end /* create sysreplicationalerts table */ IF EXISTS (SELECT * FROM msdb..sysobjects WHERE name = 'sysreplicationalerts' and xtype = 'U') begin DROP TABLE msdb..sysreplicationalerts if @@error<> 0 goto FAILURE end /* create MSagent_profiles table */ IF EXISTS (SELECT * FROM msdb..sysobjects WHERE name = 'MSagent_profiles' and xtype = 'U') begin DROP TABLE msdb..MSagent_profiles if @@error<> 0 goto FAILURE end /* create MSagent_parameters table */ IF EXISTS (SELECT * FROM msdb..sysobjects WHERE name = 'MSagent_parameters' and xtype = 'U') begin DROP TABLE msdb..MSagent_parameters if @@error<> 0 goto FAILURE end /* create MSdatatype_mappings table */ IF EXISTS (SELECT * FROM msdb..sysobjects WHERE name = 'MSdatatype_mappings' and xtype = 'U') begin DROP TABLE msdb..MSdatatype_mappings if @@error<> 0 goto FAILURE end CREATE TABLE msdb.dbo.MSdistpublishers ( name sysname NOT NULL, distribution_db sysname NOT NULL, working_directory nvarchar(255) NOT NULL, security_mode int NOT NULL, login sysname NOT NULL, password sysname NULL, active bit NOT NULL, trusted bit NOT NULL, thirdparty_flag bit NOT NULL ) if @@error<> 0 goto FAILURE CREATE UNIQUE CLUSTERED INDEX uc1MSdistpublishers ON msdb.dbo.MSdistpublishers(name) if @@error<> 0 goto FAILURE CREATE TABLE msdb.dbo.MSdistributiondbs ( name sysname NOT NULL, min_distretention int NOT NULL, max_distretention int NOT NULL, history_retention int NOT NULL ) if @@error<> 0 goto FAILURE CREATE UNIQUE CLUSTERED INDEX uc1MSdistributiondbs ON msdb.dbo.MSdistributiondbs(name) if @@error<> 0 goto FAILURE CREATE TABLE msdb.dbo.MSdistributor ( property sysname NOT NULL, value nvarchar(3000) NULL ) if @@error<> 0 goto FAILURE CREATE UNIQUE CLUSTERED INDEX uc1MSdistributor ON msdb.dbo.MSdistributor(property) if @@error<> 0 goto FAILURE CREATE TABLE msdb.dbo.sysreplicationalerts ( alert_id int identity(1,1) NOT NULL, status int NOT NULL, agent_type int NULL, agent_id int NULL, error_id int NULL, alert_error_code int NULL, time datetime NOT NULL, publisher sysname NULL, publisher_db sysname NULL, publication sysname NULL, publication_type int NULL, subscriber sysname NULL, subscriber_db sysname NULL, article sysname NULL, destination_object sysname NULL, source_object sysname NULL, alert_error_text ntext NULL ) if @@error<> 0 goto FAILURE CREATE UNIQUE CLUSTERED INDEX ucsysreplicationalerts ON msdb.dbo.sysreplicationalerts(alert_id) if @@error<> 0 goto FAILURE CREATE TABLE msdb.dbo.MSagent_profiles ( profile_id int NOT NULL IDENTITY, profile_name sysname NOT NULL, agent_type int NOT NULL, -- 1-Snapshot, 2-Logreader, -- 3-Distribution, 4-Merge type int NOT NULL, -- 0-System, 1-Custom description nvarchar(3000) NULL, def_profile bit NOT NULL ) if @@error<> 0 goto FAILURE CREATE UNIQUE CLUSTERED INDEX ucMSagent_profiles ON msdb.dbo.MSagent_profiles (profile_name, profile_id, agent_type) if @@error<> 0 goto FAILURE CREATE TABLE msdb.dbo.MSagent_parameters ( profile_id int NOT NULL, parameter_name sysname NOT NULL, value nvarchar(255) NOT NULL ) if @@error<> 0 goto FAILURE CREATE UNIQUE CLUSTERED INDEX ucMSagent_parameters ON msdb.dbo.MSagent_parameters (parameter_name, profile_id) if @@error<> 0 goto FAILURE /* ** Create default / non default profiles ** for all the agents */ /* ** Snapshot agent */ set @profile_id = NULL set @profile_name = formatmessage(20545) -- Default Snapshot Profile set @profile_desc = NULL exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 1, -- 1-Snapshot, 2-Logreader, 3-Distribution, 4-Merge @profile_type = 0, -- 0-System, 1-Custom @description = @profile_desc, @default = 1 if (@retcode = 1 or @@ERROR <> 0) goto FAILURE exec @retcode = dbo.sp_generate_agent_parameter @profile_id if (@retcode = 1 or @@ERROR <> 0) goto FAILURE /* ** Logreader agent */ set @profile_id = NULL set @profile_name = formatmessage(20545) -- Default LogReader Profile set @profile_desc = NULL exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 2, -- 1-Snapshot, 2-Logreader, 3-Distribution, 4-Merge @profile_type = 0, -- 0-System, 1-Custom @description = @profile_desc, @default = 1 if (@retcode = 1 or @@ERROR <> 0) goto FAILURE exec @retcode = dbo.sp_generate_agent_parameter @profile_id if (@retcode = 1 or @@ERROR <> 0) goto FAILURE /* ** Logreader agent - Verbose History Profile */ set @profile_id = NULL set @profile_name = formatmessage(20546) -- LogReader Verbose History Profile set @profile_desc = formatmessage(20547) exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 2, -- 1-Snapshot, 2-Logreader, 3-Distribution, 4-Merge @profile_type = 0, -- 0-System, 1-Custom @description = @profile_desc, @default = 0 if (@retcode = 1 or @@ERROR <> 0) goto FAILURE exec @retcode = dbo.sp_generate_agent_parameter @profile_id if (@retcode = 1 or @@ERROR <> 0) goto FAILURE /* ** Distribution agent */ set @profile_id = NULL set @profile_name = formatmessage(20545) -- Default Distribution Profile set @profile_desc = NULL exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 3, -- 1-Snapshot, 2-Logreader, 3-Distribution, 4-Merge @profile_type = 0, -- 0-System, 1-Custom @description = @profile_desc, @default = 1 if (@retcode = 1 or @@ERROR <> 0) goto FAILURE exec @retcode = dbo.sp_generate_agent_parameter @profile_id if (@retcode = 1 or @@ERROR <> 0) goto FAILURE /* ** Distribution Agent Verbose History Profile */ set @profile_id = NULL set @profile_name = formatmessage(20546) -- Distribution Verbose History Profile set @profile_desc = formatmessage(20547) exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 3, -- 1-Snapshot, 2-Logreader, 3-Distribution, 4-Merge @profile_type = 0, -- 0-System, 1-Custom @description = @profile_desc, @default = 0 if (@retcode = 1 or @@ERROR <> 0) goto FAILURE exec @retcode = dbo.sp_generate_agent_parameter @profile_id if (@retcode = 1 or @@ERROR <> 0) goto FAILURE /* ** Merge agent : Default profile for well connected scenarios */ set @profile_id = NULL set @profile_name = formatmessage(20545) -- Default Merge Profile set @profile_desc = NULL exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 4, -- 1-Snapshot, 2-Logreader, 3-Distribution, 4-Merge @profile_type = 0, -- 0-System, 1-Custom @description = @profile_desc, @default = 1 if (@retcode = 1 or @@ERROR <> 0) goto FAILURE exec @retcode = dbo.sp_generate_agent_parameter @profile_id if (@retcode = 1 or @@ERROR <> 0) goto FAILURE /* ** Merge agent : Non default profile for disconnected scenarios ( unreliable link ) */ set @profile_id = NULL set @profile_name = formatmessage(20548) -- Non-Default Merge Profile set @profile_desc = formatmessage(20549) exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 4, -- 1-Snapshot, 2-Logreader, 3-Distribution, 4-Merge @profile_type = 0, -- 0-System, 1-Custom @description = @profile_desc, @default = 0 if (@retcode = 1 or @@ERROR <> 0) goto FAILURE exec @retcode = dbo.sp_generate_agent_parameter @profile_id if (@retcode = 1 or @@ERROR <> 0) goto FAILURE /* ** Merge agent : Non default profile for verbose histroy */ set @profile_id = NULL set @profile_name = formatmessage(20546) -- Verbose Merge Profile set @profile_desc = formatmessage(20547) exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 4, -- 1-Snapshot, 2-Logreader, 3-Distribution, 4-Merge @profile_type = 0, -- 0-System, 1-Custom @description = @profile_desc, @default = 0 if (@retcode = 1 or @@ERROR <> 0) goto FAILURE exec @retcode = dbo.sp_generate_agent_parameter @profile_id if (@retcode = 1 or @@ERROR <> 0) goto FAILURE /* ** Merge agent : Synchronization Manager Profile */ set @profile_id = NULL set @profile_name = formatmessage(20550) -- SyncMgr Profile set @profile_desc = formatmessage(20551) exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 4, -- 1-Snapshot, 2-Logreader, 3-Distribution, 4-Merge @profile_type = 0, -- 0-System, 1-Custom @description = @profile_desc, @default = 0 if (@retcode = 1 or @@ERROR <> 0) goto FAILURE exec @retcode = dbo.sp_generate_agent_parameter @profile_id if (@retcode = 1 or @@ERROR <> 0) goto FAILURE /* ** Distribution agent : Synchronization Manager Profile */ set @profile_id = NULL set @profile_name = formatmessage(20550) -- SyncMgr Profile set @profile_desc = formatmessage(20551) exec @retcode = dbo.sp_add_agent_profile @profile_id = @profile_id OUT, @profile_name = @profile_name, @agent_type = 3, -- 1-Snapshot, 2-Logreader, 3-Distribution, 4-Merge @profile_type = 0, -- 0-System, 1-Custom @description = @profile_desc, @default = 0 if (@retcode = 1 or @@ERROR <> 0) goto FAILURE exec @retcode = dbo.sp_generate_agent_parameter @profile_id if (@retcode = 1 or @@ERROR <> 0) goto FAILURE create table msdb.dbo.MSdatatype_mappings ( dbms_name sysname NOT NULL, sql_type sysname NOT NULL, dest_type sysname NOT NULL, dest_prec int NOT NULL, dest_create_params int NOT NULL, dest_nullable bit NOT NULL ) exec dbo.sp_add_datatype_mapping 'MS Jet', 'binary' , 'binary', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'varbinary' , 'varbinary', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'binary' , 'image', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'varbinary' , 'image', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'varchar' , 'varchar', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'varchar' , 'longtext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'nchar' , 'nchar', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'nchar' , 'longtext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'char' , 'char', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'char' , 'longtext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'nvarchar' , 'nchar varying', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'nvarchar' , 'longtext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'datetime' , 'datetime', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'smalldatetime' , 'datetime', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'decimal' , 'decimal', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'numeric' , 'decimal', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'float' , 'float', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'real' , 'real', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'int' , 'int', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'smallint' , 'smallint', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'tinyint' , 'byte', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'money' , 'currency', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'smallmoney' , 'currency', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'bit' , 'bit', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'sysname' , 'nchar varying', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'timestamp' , 'binary', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'uniqueidentifier' , 'guid', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'text' , 'longtext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'ntext' , 'longtext', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'MS Jet', 'image' , 'image', 1073741824, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'binary' , 'raw', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'varbinary' , 'raw', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'binary' , 'long raw', 2147483647, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'varbinary' , 'long raw', 2147483647, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'varchar' , 'char', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'varchar' , 'varchar2', 2000, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'varchar' , 'long', 2147483647, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'nchar' , 'char', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'nchar' , 'varchar2', 2000, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'nchar' , 'long', 2147483647, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'char' , 'char', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'char' , 'varchar2', 2000, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'char' , 'long', 2147483647, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'nvarchar' , 'char', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'nvarchar' , 'varchar2', 2000, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'nvarchar' , 'long', 2147483647, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'datetime' , 'char', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'smalldatetime' , 'date', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'decimal' , 'number', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'numeric' , 'number', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'float' , 'float', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'real' , 'float', 255, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'int' , 'number', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'smallint' , 'number', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'tinyint' , 'number', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'money' , 'number', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'smallmoney' , 'number', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'bit' , 'number', 255, 3, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'sysname' , 'char', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'timestamp' , 'raw', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'uniqueidentifier' , 'char', 255, 4, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'text' , 'long', 2147483647, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'ntext' , 'long', 2147483647, 0, 1 exec dbo.sp_add_datatype_mapping 'Oracle', 'image' , 'long raw', 2147483647, 0, 1 return 0 FAILURE: return 1 go -------------------------------------------------------------------------------- --. sp_addsubscriber -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_addsubscriber') drop procedure sp_addsubscriber go raiserror('Creating procedure sp_addsubscriber', 0,1) GO CREATE PROCEDURE sp_addsubscriber ( @subscriber sysname, @type tinyint = 0, @login sysname = 'sa', @password sysname = NULL, @commit_batch_size int = 100, @status_batch_size int = 100, @flush_frequency int = 0, @frequency_type int = 64, @frequency_interval int = 1, @frequency_relative_interval int = 1, @frequency_recurrence_factor int = 0, @frequency_subday int = 4, @frequency_subday_interval int = 5, @active_start_time_of_day int = 0, @active_end_time_of_day int = 235959, @active_start_date int = 0, @active_end_date int = 99991231, @description nvarchar (255) = NULL, @security_mode int = 1, /* backward compatible */ /* 0 standard; 1 integrated */ @encrypted_password bit = 0 ) AS DECLARE @distributor sysname DECLARE @distribdb sysname DECLARE @distproc nvarchar (255) DECLARE @retcode int DECLARE @dsn_subscriber tinyint DECLARE @jet_subscriber tinyint DECLARE @oledb_subscriber tinyint DECLARE @dist_rpcname sysname DECLARE @platform_nt binary -- Defined in sqlrepl.h select @dsn_subscriber = 1 /* Const: subscriber type 'dsn' */ select @jet_subscriber = 2 select @oledb_subscriber = 3 select @platform_nt = 0x1 /* ** Check if replication components are installed on this server */ exec @retcode = dbo.sp_MS_replication_installed if (@retcode <> 1) begin return (1) end /* ** Parameter Check: @subscriber. ** Check to make sure that the subscriber doesn't already exist, and ** that the name is a valid non-null identifier. */ IF @subscriber IS NULL BEGIN RAISERROR (14043, 16, -1, '@subscriber') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @subscriber IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) if LOWER(@subscriber) = 'all' BEGIN RAISERROR (14032, 16, -1, '@subscriber') RETURN (1) END /* ** Check for invalid security mode */ IF @security_mode < 0 OR @security_mode > 1 BEGIN RAISERROR(14109, 16, -1) RETURN (1) END IF (UPPER(@subscriber) = UPPER(@@SERVERNAME) and @platform_nt != ( platform() & @platform_nt ) and @security_mode = 1) BEGIN RAISERROR(21038, 16, -1) RETURN (1) END -- Clear the password if the security mode is 1 if @security_mode = 1 select @password = '' IF EXISTS (SELECT * FROM master..sysservers WHERE UPPER(srvname) = UPPER(@subscriber) AND srvstatus & 4 <> 0) BEGIN RAISERROR (14040, 16, -1, @subscriber) RETURN (1) END IF @password = N'' select @password = NULL /* ** If no MSsubscriber_info parameters skip RPC code. */ IF @frequency_type = -1 GOTO ADDSUB /* ** Get distribution server information for remote RPC ** subscription calls. */ /* BEGIN TRAN addsubscriber */ EXEC @retcode = dbo.sp_helpdistributor @distributor = @distributor OUTPUT, @rpcsrvname = @dist_rpcname OUTPUT, @distribdb = @distribdb OUTPUT IF @@error <> 0 BEGIN RAISERROR (14071, 16, -1) goto undo END IF @retcode <> 0 OR @distribdb IS NULL OR @distributor IS NULL BEGIN RAISERROR (14071, 16, -1) goto undo END DECLARE @zeroint int SELECT @zeroint = 0 /* ** Insert information into MSsubscriber_info */ SELECT @distproc = RTRIM(@dist_rpcname) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSadd_subscriber_info' EXEC @retcode = @distproc @@SERVERNAME, @subscriber, @type, @login, @password, @commit_batch_size, @status_batch_size, @flush_frequency, @frequency_type, @frequency_interval, @frequency_relative_interval, @frequency_recurrence_factor, @frequency_subday, @frequency_subday_interval, @active_start_time_of_day, @active_end_time_of_day, @active_start_date, @active_end_date, /* Work around of server RPC named parameter problem */ @retryattempts = @zeroint, @retrydelay = @zeroint, @description = @description, @security_mode = @security_mode, @encrypted_password = @encrypted_password IF @@error <> 0 OR @retcode <> 0 BEGIN RAISERROR (14042, 16, -1) goto undo END /* ** add schedule information into MSsubscriber_schedule for merge agent */ -- NOTE: We may need better default schedule for merge agent SELECT @distproc = RTRIM(@dist_rpcname) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSadd_subscriber_schedule' EXEC @retcode = @distproc @@SERVERNAME, @subscriber, 0, -- agent_type = 0 means distribution agent @frequency_type, @frequency_interval, @frequency_relative_interval, @frequency_recurrence_factor, @frequency_subday, @frequency_subday_interval, @active_start_time_of_day, @active_end_time_of_day, @active_start_date, @active_end_date IF @@error <> 0 OR @retcode <> 0 BEGIN RAISERROR (14042, 16, -1) goto undo END EXEC @retcode = @distproc @@SERVERNAME, @subscriber, 1, --agent_type = 0 means merge agent 4, --frequency_type, 1, --frequency_interval, 1, --frequency_relative_interval, 0, --frequency_recurrence_factor, 8, --frequency_subday, 1, --frequency_subday_interval, 0, --active_start_time_of_day, 235959, --active_end_time_of_day, 0, --active_start_date, 99991231 --active_end_date IF @@error <> 0 OR @retcode <> 0 BEGIN RAISERROR (14042, 16, -1) goto undo END /* Commit Transaction addsubscriber */ ADDSUB: /* ** The server may already be listed in master..sysservers, but might ** not be marked as a subscriber yet. If it's not in ** master..sysservers, let's add it first. */ IF NOT EXISTS (SELECT * FROM master..sysservers WHERE LOWER(srvname) = LOWER(@subscriber)) begin EXECUTE @retcode = dbo.sp_addserver @subscriber IF @@error <> 0 OR @retcode <> 0 BEGIN RAISERROR (14042, 16, -1) RETURN (1) END end /* ** Set the server option to indicate this is a subscriber. */ EXECUTE @retcode = dbo.sp_serveroption @subscriber, 'sub', true IF @@error <> 0 OR @retcode <> 0 BEGIN RAISERROR (14042, 16, -1) RETURN (1) END /* ** Set the server option to indicate this is a DSN subscriber. */ if @type = @dsn_subscriber OR @type = @jet_subscriber OR @type = @oledb_subscriber BEGIN update master..sysservers set srvproduct = 'MSREPL-NONSQL' where UPPER(srvname) = UPPER(@subscriber) IF @@error <> 0 return(1) END RETURN (0) undo: RETURN (1) GO -------------------------------------------------------------------------------- --. sp_changesubscriber -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_changesubscriber') drop procedure sp_changesubscriber go raiserror('Creating procedure sp_changesubscriber', 0,1) GO CREATE PROCEDURE sp_changesubscriber ( @subscriber sysname, @type tinyint = NULL, @login sysname = NULL, @password sysname = '%', @commit_batch_size int = NULL, @status_batch_size int = NULL, @flush_frequency int = NULL, @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, @description nvarchar (255) = NULL, @security_mode int = NULL /* 0 standard; 1 integrated */ ) AS DECLARE @distributor sysname DECLARE @distribdb sysname DECLARE @distproc nvarchar (255) DECLARE @msg nvarchar(255) DECLARE @retcode int DECLARE @platform_nt binary select @platform_nt = 0x1 IF (UPPER(@subscriber) = UPPER(@@SERVERNAME) and @platform_nt != ( platform() & @platform_nt ) and @security_mode = 1) BEGIN RAISERROR(21038, 16, -1) RETURN (1) END -- Clear the password if the security mode is 1 if @security_mode = 1 select @password = '' /* ** Check to make sure that the subscriber exists. */ IF NOT EXISTS (SELECT * FROM master..sysservers WHERE UPPER(srvname) = UPPER(@subscriber)) BEGIN RAISERROR(14048, 16, 1, @subscriber) RETURN (1) END /* ** Get distribution server information for remote RPC ** subscription calls. */ 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 DECLARE @intnull int /* ** Update MSsubscriber_info */ SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSupdate_subscriber_info' EXEC @retcode = @distproc @@SERVERNAME, @subscriber, @type, @login, @password, @commit_batch_size, @status_batch_size, @flush_frequency, @frequency_type, @frequency_interval, @frequency_relative_interval, @frequency_recurrence_factor, @frequency_subday, @frequency_subday_interval, @active_start_time_of_day, @active_end_time_of_day, @active_start_date, @active_end_date, @retryattempts = @intnull, @retrydelay = @intnull, @description = @description, @security_mode = @security_mode IF @@ERROR <> 0 OR @retcode <> 0 BEGIN RAISERROR (14048, 16, -1, @subscriber) RETURN (1) END go -------------------------------------------------------------------------------- --. sp_MScreate_dist_tables -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MScreate_dist_tables') drop procedure sp_MScreate_dist_tables go raiserror('Creating procedure sp_MScreate_dist_tables', 0,1) GO CREATE PROCEDURE sp_MScreate_dist_tables AS /* ** Important: ** We use varbinary(16) for xact_id and xact_seqno, we don't want ending nulls ** to be truncated by the server ** ** Also, in MSrepl_commands, we don't want ending space to be truncated. */ SET ANSI_PADDING ON IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSrepl_version' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSrepl_version', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSrepl_version ( major_version int NOT NULL, minor_version int NOT NULL, revision int NOT NULL, db_existed bit NULL ) EXEC dbo.sp_MS_marksystemobject 'MSrepl_version' raiserror('Creating clustered index ucMSrepl_version', 0,1) CREATE UNIQUE CLUSTERED INDEX ucMSrepl_version ON dbo.MSrepl_version (major_version, minor_version, revision) INSERT INTO MSrepl_version VALUES (7,0,0,0) END IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSpublisher_databases' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSpublisher_databases', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSpublisher_databases( publisher_id smallint NOT NULL, publisher_db sysname NULL, id int identity NOT NULL, ) EXEC dbo.sp_MS_marksystemobject 'MSpublisher_databases' raiserror('Creating clustered index ucMSpublisher_databases', 0,1) CREATE UNIQUE CLUSTERED INDEX ucMSpublisher_databases ON dbo.MSpublisher_databases (publisher_id, publisher_db, id) END IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSpublications' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSpublications', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSpublications ( publisher_id smallint NOT NULL, publisher_db sysname NULL, publication sysname NOT NULL, publication_id int identity NOT NULL, -- This id IS NOT the same as the SQL Server publisher's publication_type int NOT NULL, -- 0 = Snapshot 1 = Transactional thirdparty_flag bit NOT NULL, -- 0 = SQL Server 1 = Third Party independent_agent bit NOT NULL, immediate_sync bit NOT NULL, allow_push bit NOT NULL, allow_pull bit NOT NULL, allow_anonymous bit NOT NULL, description nvarchar(255) NULL, vendor_name nvarchar(100) NULL, retention int NULL ) EXEC dbo.sp_MS_marksystemobject 'MSpublications' -- publication_id needs to be the first columns in the index. It -- is used in sp_MSmaximum_cleanup_seqno. raiserror('Creating clustered index ucMSpublications', 0,1) CREATE UNIQUE CLUSTERED INDEX ucMSpublications ON dbo.MSpublications (publication_id, publication, publisher_db, publisher_id) END IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSarticles' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSarticles', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSarticles ( publisher_id smallint NOT NULL, publisher_db sysname NULL, publication_id int NOT NULL, article sysname NOT NULL, article_id int NOT NULL, -- This id is the same as a SQL Server Publisher's destination_object sysname NULL, source_owner sysname NULL, source_object sysname NULL, description nvarchar(255) NULL ) EXEC dbo.sp_MS_marksystemobject 'MSarticles' raiserror('Creating clustered index ucMSarticles', 0,1) CREATE UNIQUE CLUSTERED INDEX ucMSarticles ON dbo.MSarticles (publisher_db, publisher_id, article_id, article, publication_id) END IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSsubscriptions' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSsubscriptions', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSsubscriptions ( publisher_database_id int NOT NULL, -- Used to reference MSrepl_transactions and MSrepl_commands publisher_id smallint NOT NULL, publisher_db sysname NOT NULL, publication_id int NOT NULL, article_id int NOT NULL, subscriber_id smallint NOT NULL, subscriber_db sysname NOT NULL, subscription_type int NOT NULL, -- 0 = push, 1 = pull, 2 = anonymous sync_type tinyint NOT NULL, -- 1 = automatic 2 = no sync status tinyint NOT NULL, -- 0 = inactive, 1 = subscribed, 2 = active subscription_seqno varbinary(16) NOT NULL, -- publisher's database sequence number snapshot_seqno_flag bit NOT NULL, -- 1 if subscription_seqno is the snapshot seqno independent_agent bit NOT NULL, -- Value carried over from MSpublications subscription_time datetime NOT NULL, loopback_detection bit NOT NULL, agent_id int NOT NULL, update_mode tinyint NOT NULL, publisher_seqno varbinary(16) NOT NULL ) EXEC dbo.sp_MS_marksystemobject 'MSsubscriptions' raiserror('Creating clustered index ucMSsubscirptions', 0,1) CREATE UNIQUE CLUSTERED INDEX ucMSsubscriptions ON dbo.MSsubscriptions (agent_id, article_id) -- Index used by sp_MSdelete_publisherdb_trans raiserror('Creating index iMSsubscriptions', 0,1) CREATE INDEX iMSsubscriptions ON dbo.MSsubscriptions (publisher_database_id, article_id, subscriber_id, subscriber_db, publication_id, publisher_db, publisher_id) END -- For beta 3 upgrade, we need to create new index here. if not exists (select * from sysindexes where name = 'iMSsubscriptions2') begin -- Index used by sp_MSdelete_publisherdb_trans raiserror('Creating index iMSsubscriptions2', 0,1) CREATE INDEX iMSsubscriptions2 ON dbo.MSsubscriptions (publisher_database_id, subscription_seqno) end IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSmerge_subscriptions' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSmerge_subscriptions', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSmerge_subscriptions ( publisher_id smallint NOT NULL, publisher_db sysname NULL, publication_id int NOT NULL, subscriber_id smallint NOT NULL, subscriber_db sysname NULL, subscription_type int NULL, -- 0 = push, 1 = pull, 2 = anonymous sync_type tinyint NOT NULL, -- 1 = automatic 2 = no sync status tinyint NOT NULL, -- 0 = inactive, 1 = subscribed, 2 = active subscription_time datetime NOT NULL ) EXEC dbo.sp_MS_marksystemobject 'MSmerge_subscriptions' raiserror('Creating clustered index ucMSmerge_subscriptions', 0,1) CREATE UNIQUE CLUSTERED INDEX ucMSmerge_subscriptions ON dbo.MSmerge_subscriptions (publisher_id, publisher_db, publication_id, subscriber_id, subscriber_db) END IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSrepl_transactions' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSrepl_transactions', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSrepl_transactions ( publisher_database_id int NOT NULL, xact_id varbinary(16) NULL, xact_seqno varbinary (16 ) NOT NULL, entry_time datetime NOT NULL ) EXEC dbo.sp_MS_marksystemobject 'MSrepl_transactions' raiserror('Creating clustered index usMSrepl_transactions', 0,1) CREATE UNIQUE CLUSTERED INDEX ucMSrepl_transactions ON dbo.MSrepl_transactions (publisher_database_id, xact_seqno) END IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSrepl_commands' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSrepl_commands', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSrepl_commands ( publisher_database_id int not null, xact_seqno varbinary(16) not null, type int not null, article_id int not null, originator_id int not null, command_id int not null, partial_command bit not null, command varbinary(1024) NULL ) EXEC dbo.sp_MS_marksystemobject 'MSrepl_commands' raiserror('Creating clusterd index ucMSrepl_commands', 0,1) CREATE UNIQUE CLUSTERED INDEX ucMSrepl_commands ON dbo.MSrepl_commands (publisher_database_id, xact_seqno, command_id) END IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSrepl_originators' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSrepl_orginators', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSrepl_originators ( id int identity not null, publisher_database_id int not null, srvname sysname not null, dbname sysname not null ) EXEC dbo.sp_MS_marksystemobject 'MSrepl_originators' raiserror('Creating clustered index usMSrepl_originators', 0,1) CREATE UNIQUE CLUSTERED INDEX ucMSrepl_originators ON dbo.MSrepl_originators (publisher_database_id, srvname, dbname) END IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSsubscriber_info' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSsubscriber_info', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSsubscriber_info ( publisher sysname NOT NULL, subscriber sysname NOT NULL, type tinyint NOT NULL, /* 0: MS SQL Server 1: ODBC Data Source */ login sysname NULL, password sysname NULL, description nvarchar(255) NULL, security_mode int NOT NULL ) EXEC dbo.sp_MS_marksystemobject 'MSsubscriber_info' raiserror('Creating clustered index ucMSsubscriber_info', 0,1) CREATE UNIQUE CLUSTERED INDEX ucMSsubscriber_info ON dbo.MSsubscriber_info (publisher, subscriber) END ELSE BEGIN IF NOT EXISTS (select * from syscolumns where name = 'description' and id=object_id('MSsubscriber_info')) BEGIN ALTER TABLE MSsubscriber_info ADD description nvarchar (255) NULL UPDATE MSsubscriber_info SET description = 'SQL Server 6.0' END END IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSsubscriber_schedule' and type = 'U') BEGIN raiserror('Creating table MSsubscriber_schedule', 0,1) CREATE TABLE dbo.MSsubscriber_schedule ( publisher sysname NOT NULL, subscriber sysname NOT NULL, agent_type smallint NOT NULL, -- 0 for distribution agent, 1 for merge agent frequency_type int NOT NULL, frequency_interval int NOT NULL, frequency_relative_interval int NOT NULL, frequency_recurrence_factor int NOT NULL, frequency_subday int NOT NULL, frequency_subday_interval int NOT NULL, active_start_time_of_day int NOT NULL, active_end_time_of_day int NOT NULL, active_start_date int NOT NULL, active_end_date int NOT NULL ) EXEC dbo.sp_MS_marksystemobject 'MSsubscriber_schedule' CREATE UNIQUE CLUSTERED INDEX ucMSsubscriber_schedule ON dbo.MSsubscriber_schedule (publisher, subscriber, agent_type) END IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSsnapshot_history' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSsnapshot_history', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSsnapshot_history ( agent_id int NOT NULL, runstatus int NOT NULL, start_time datetime NOT NULL, time datetime NOT NULL, duration int NOT NULL, comments nvarchar(255) NOT NULL, -- Session summary statistics delivered_transactions int NOT NULL, delivered_commands int NOT NULL, delivery_rate float NOT NULL, error_id int NOT NULL, timestamp NOT NULL ) EXEC dbo.sp_MS_marksystemobject 'MSsnapshot_history' raiserror('Creating clustered index ucMSsnapshot_history', 0,1) CREATE UNIQUE CLUSTERED INDEX ucMSsnapshot_history ON dbo.MSsnapshot_history (agent_id, timestamp, start_time, time) if not exists (select * from sysindexes where name = 'nc1MSsnapshot_history') begin raiserror('Creating clustered index nc1MSsnapshot_history', 0,1) create nonclustered index nc1MSsnapshot_history on MSsnapshot_history(agent_id, start_time) end END IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSlogreader_history' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSlogreader_history', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSlogreader_history ( agent_id int NOT NULL, runstatus int NOT NULL, start_time datetime NOT NULL, time datetime NOT NULL, duration int NOT NULL, comments nvarchar(255) NOT NULL, xact_seqno varbinary(16) NULL, -- Session summary statistics delivery_time int NOT NULL, delivered_transactions int NOT NULL, delivered_commands int NOT NULL, average_commands int NOT NULL, delivery_rate float NOT NULL, delivery_latency int NOT NULL, error_id int NOT NULL, timestamp NOT NULL ) EXEC dbo.sp_MS_marksystemobject 'MSlogreader_history' raiserror('Creating clustered index ucMSlogreader_history', 0,1) CREATE UNIQUE CLUSTERED INDEX ucMSlogreader_history ON dbo.MSlogreader_history (agent_id, timestamp, runstatus, start_time, time) if not exists (select * from sysindexes where name = 'nc1MSlogreader_history') begin raiserror('Creating nonclustered index nc1MSlogreader_history', 0,1) create nonclustered index nc1MSlogreader_history on MSlogreader_history(agent_id, start_time) end END IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSdistribution_history' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSdistribution_history', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSdistribution_history ( agent_id int NOT NULL, runstatus int NOT NULL, start_time datetime NOT NULL, time datetime NOT NULL, duration int NOT NULL, comments nvarchar(255) NOT NULL, xact_seqno varbinary(16) NULL, -- Current statistics current_delivery_rate float NOT NULL, current_delivery_latency int NOT NULL, -- Session summary statistics delivered_transactions int NOT NULL, delivered_commands int NOT NULL, average_commands int NOT NULL, delivery_rate float NOT NULL, delivery_latency int NOT NULL, -- Summary statistics across all sessions total_delivered_commands int NOT NULL, error_id int NOT NULL, updateable_row bit NOT NULL, timestamp NOT NULL ) EXEC dbo.sp_MS_marksystemobject 'MSdistribution_history' raiserror('Creating clustered index ucMSdistribution_history', 0,1) CREATE UNIQUE CLUSTERED INDEX ucMSdistribution_history ON dbo.MSdistribution_history (agent_id, timestamp, runstatus, start_time, time) if not exists (select * from sysindexes where name = 'nc1MSdistribution_history') begin raiserror('Creating clustered index nc1MSdistribution_history', 0,1) create nonclustered index nc1MSdistribution_history on MSdistribution_history(agent_id, start_time) end END IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSmerge_history' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSmerge_history', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSmerge_history ( agent_id int NOT NULL, runstatus int NOT NULL, start_time datetime NOT NULL, time datetime NOT NULL, duration int NOT NULL, comments nvarchar(255) NOT NULL, delivery_time int NOT NULL, delivery_rate float NOT NULL, publisher_insertcount int NULL, publisher_updatecount int NULL, publisher_deletecount int NULL, publisher_conflictcount int NULL, subscriber_insertcount int NULL, subscriber_updatecount int NULL, subscriber_deletecount int NULL, subscriber_conflictcount int NULL, error_id int NOT NULL, timestamp NOT NULL, updateable_row bit NOT NULL ) EXEC dbo.sp_MS_marksystemobject 'MSmerge_history' raiserror('Creating clustered index ucMSmerge_history', 0,1) CREATE UNIQUE CLUSTERED INDEX ucMSmerge_history ON dbo.MSmerge_history (agent_id, timestamp, runstatus, start_time, time) if not exists (select * from sysindexes where name = 'nc1MSmerge_history') begin raiserror('Creating nonclustered index nc1MSmerge_history', 0,1) create nonclustered index nc1MSmerge_history on MSmerge_history(agent_id, start_time) end END ELSE BEGIN IF NOT EXISTS (select * from syscolumns where name = 'updateable_row' and id=object_id('MSmerge_history')) BEGIN ALTER TABLE MSmerge_history ADD updateable_row bit default 1 NOT NULL if not exists (select * from sysindexes where name = 'nc1MSmerge_history') begin raiserror('Creating nonclustered index nc1MSmerge_history', 0,1) create nonclustered index nc1MSmerge_history on MSmerge_history(agent_id, start_time) end END END IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSrepl_errors' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSrepl_errors', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSrepl_errors ( id int NOT NULL, time datetime NOT NULL, error_type_id int NULL, source_type_id int NULL, source_name nvarchar(100) NULL, error_code sysname NULL, error_text ntext NULL ) EXEC dbo.sp_MS_marksystemobject 'MSrepl_errors' raiserror('Creating clustered index ucMSrepl_errors', 0,1) CREATE CLUSTERED INDEX ucMSrepl_errors ON dbo.MSrepl_errors (id, time) -- WITH ALLOW_DUP_ROW END IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSsnapshot_agents' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSsnapshot_agents', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSsnapshot_agents ( id int IDENTITY NOT NULL, name nvarchar(100) NOT NULL, publisher_id smallint NOT NULL, publisher_db sysname NOT NULL, publication sysname NOT NULL, publication_type int NOT NULL, -- 0 transactional 1 snapshot 2 merge local_job bit NOT NULL, job_id binary(16) NULL, profile_id int NOT NULL ) EXEC dbo.sp_MS_marksystemobject 'MSsnapshot_agents' raiserror('Creating clustered index ucMSsnapshot_agents', 0,1) CREATE CLUSTERED INDEX ucMSsnapshot_agents ON dbo.MSsnapshot_agents (publication, publisher_db, publisher_id) raiserror('Creatingindex iMSsnapshot_agents', 0,1) CREATE UNIQUE INDEX iMSsnapshot_agents ON dbo.MSsnapshot_agents (id) END IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSlogreader_agents' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSlogreader_agents', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSlogreader_agents ( id int IDENTITY NOT NULL, name nvarchar(100) NOT NULL, publisher_id smallint NOT NULL, publisher_db sysname NOT NULL, publication sysname NOT NULL,-- Not used for SQL Server publisher local_job bit NOT NULL, job_id binary(16) NULL, profile_id int NOT NULL ) EXEC dbo.sp_MS_marksystemobject 'MSlogreader_agents' raiserror('Creating clustered index ucMSlogreader_agents', 0,1) CREATE CLUSTERED INDEX ucMSlogreader_agents ON dbo.MSlogreader_agents (publisher_db, publisher_id) raiserror('Creatingindex iMSlogreader_agents', 0,1) CREATE UNIQUE INDEX iMSlogreader_agents ON dbo.MSlogreader_agents (id) END IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSdistribution_agents' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSdistribution_agents', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSdistribution_agents ( id int IDENTITY NOT NULL, name nvarchar(100) NOT NULL, publisher_database_id int NOT NULL, publisher_id smallint NOT NULL, publisher_db sysname NOT NULL, publication sysname NOT NULL, subscriber_id smallint NULL, subscriber_db sysname NULL, subscription_type int NOT NULL, local_job bit NULL, job_id binary(16) NULL, subscription_guid binary(16) NOT NULL, profile_id int NOT NULL, anonymous_subid uniqueidentifier NULL, subscriber_name sysname NULL, virtual_agent_id int NULL, anonymous_agent_id int NULL, creation_date datetime default (getdate()) not NULL ) EXEC dbo.sp_MS_marksystemobject 'MSdistribution_agents' raiserror('Creating clustered index ucMSdistribution_agents', 0,1) CREATE UNIQUE CLUSTERED INDEX ucMSdistribution_agents ON dbo.MSdistribution_agents (id) raiserror('Creatingindex iMSdistribution_agents', 0,1) CREATE INDEX iMSdistribution_agents ON dbo.MSdistribution_agents (publication, publisher_db, publisher_id, subscriber_id, subscriber_db, anonymous_subid) END if not exists (select * from syscolumns where id = object_id('MSdistribution_agents') and name = 'creation_date') begin alter table MSdistribution_agents add creation_date datetime default (getdate()) not null end IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSmerge_agents' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSmerge_agents', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSmerge_agents ( id int IDENTITY NOT NULL, name nvarchar(100) NOT NULL, publisher_id smallint NOT NULL, publisher_db sysname NOT NULL, publication sysname NOT NULL, subscriber_id smallint NULL, subscriber_db sysname NULL, local_job bit NULL, job_id binary(16) NULL, profile_id int NULL, anonymous_subid uniqueidentifier NULL, subscriber_name sysname NULL, creation_date datetime default (getdate()) not NULL ) EXEC dbo.sp_MS_marksystemobject 'MSmerge_agents' raiserror('Creating clustered index ucMSmerge_agents', 0,1) CREATE CLUSTERED INDEX ucMSmerge_agents ON dbo.MSmerge_agents (publication, publisher_db, publisher_id, subscriber_id, subscriber_db, anonymous_subid) raiserror('Creatingindex iMSmerge_agents', 0,1) CREATE UNIQUE INDEX iMSmerge_agents ON dbo.MSmerge_agents (id) END if not exists (select * from syscolumns where id = object_id('MSmerge_agents') and name = 'creation_date') begin alter table MSmerge_agents add creation_date datetime default (getdate()) not null end IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSpublication_access' and type = 'U') BEGIN /****************************************************************************/ raiserror('Creating table MSpublication_access', 0,1) /****************************************************************************/ CREATE TABLE dbo.MSpublication_access ( publication_id int NULL, -- Publication_id is unique in distribution database. login sysname NOT NULL -- Logins in the publication access list, they nust -- exist at both publisher and distributor side. ) EXEC dbo.sp_MS_marksystemobject 'MSpublication_access' raiserror('Creating clustered index ucMSpublication_access', 0,1) CREATE UNIQUE CLUSTERED INDEX ucMSpublication_access ON dbo.MSpublication_access (publication_id, login) END -- For b3 upgrade if NOT EXISTS (select * from syscolumns where name='retention' and id=object_id('MSpublications')) begin alter table MSpublications add retention int NULL UPDATE msdb..MSdistributiondbs set max_distretention=72 where name = db_name() end -- drop default_access column if exists (select * from syscolumns where id = object_id('MSpublications') and name = 'default_access') begin alter table MSpublications drop column default_access end -- Drop publisher_id column if EXISTS (select * from syscolumns where name='publisher_id' and id=object_id('MSpublication_access')) begin drop index MSpublication_access.ucMSpublication_access alter table MSpublication_access drop column publisher_id raiserror('Creating clustered index ucMSpublication_access', 0,1) CREATE UNIQUE CLUSTERED INDEX ucMSpublication_access ON dbo.MSpublication_access (publication_id, login) end GO -------------------------------------------------------------------------------- --. sp_adddistributor -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_adddistributor') drop procedure sp_adddistributor go raiserror('Creating procedure sp_adddistributor', 0,1) go CREATE PROCEDURE sp_adddistributor ( @distributor sysname, /* distributor server name */ @heartbeat_interval int = 10, -- minutes @password sysname = NULL ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @retcode int DECLARE @agentname nvarchar(100) DECLARE @command nvarchar(255) DECLARE @distribution_db sysname DECLARE @distproc nvarchar(255) DECLARE @dist_rpcname sysname DECLARE @server_added bit declare @login sysname select @server_added = 0 select @login = 'distributor_admin' /* ** Check if replication components are installed on this server */ exec @retcode = dbo.sp_MS_replication_installed if (@retcode <> 1) begin return (1) end -- Must be at master db. IF db_name() <> 'master' BEGIN RAISERROR(5001, 16,-1) return (1) END /* ** Parameter Check: @distributor. ** Check to make sure that the distributor is not NULL and that it ** conforms to the rules for identifiers. */ IF @distributor IS NULL BEGIN RAISERROR (14043, 16, -1, '@distributor') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @distributor IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) IF @password = N'' select @password = NULL -- Seed default password with random value only for a local distributor. IF (@password is null) AND (UPPER(@@SERVERNAME) = UPPER(@distributor)) select @password = convert(sysname, newid()) /* ** Check to make sure that the distributor doesn't already exist. */ SELECT @dist_rpcname = NULL SELECT @dist_rpcname = srvname FROM master..sysservers WHERE srvstatus & 8 <> 0 IF @dist_rpcname IS NOT NULL BEGIN RAISERROR (14099, 16, -1, @dist_rpcname) RETURN(1) END -- drop repl_distributor if it exists. if exists (select * from master..sysservers where lower(srvname) = 'repl_distributor') begin exec @retcode = dbo.sp_dropserver 'repl_distributor', 'droplogins' IF @@error <> 0 OR @retcode <> 0 BEGIN RETURN(1) END end -- Add the linked server entry for the distributor -- Note we do this even for local server for consistancy EXECUTE @retcode = dbo.sp_addserver 'repl_distributor' IF @@error <> 0 OR @retcode <> 0 BEGIN RETURN (1) END select @server_added = 1 -- Mark system link EXECUTE @retcode = dbo.sp_serveroption 'repl_distributor', 'system','true' IF @@error <> 0 OR @retcode <> 0 BEGIN RETURN (1) END EXECUTE @retcode = dbo.sp_setnetname 'repl_distributor', @distributor IF @@error <> 0 OR @retcode <> 0 BEGIN goto UNDO END exec @retcode = dbo.sp_addlinkedsrvlogin @rmtsrvname= 'repl_distributor', @useself = 'false', @locallogin = NULL, @rmtuser = @login, @rmtpassword = @password IF @@error <> 0 OR @retcode <> 0 BEGIN goto UNDO END /* ** If this is not the local server, remote distributor must be set up first */ IF UPPER(@distributor) <> UPPER(@@SERVERNAME) BEGIN /* ** Test to see if the local server is defined as publisher ** at the remove distributor. ** Note: cannot call sp_helpdistributor locally since the server is not ** marked for distribution. ** We can not move the serveroption call before this RPC because RPC failure ** may cause the SP to terminate. Thus, we can not UNDO the server option. ** give all parameters to work around SQL SERVER 7.0 rpc named param bug. */ SELECT @distproc = 'repl_distributor.master.dbo.sp_helpdistributor' DECLARE @loc_directory nvarchar(255) DECLARE @loc_account nvarchar(255) DECLARE @loc_mindistretention int DECLARE @loc_maxdistretention int DECLARE @loc_historyretention int DECLARE @loc_historycleanupagent nvarchar(100) DECLARE @loc_distribcleanupagent nvarchar(100) DECLARE @alert_name nvarchar(100) DECLARE @alert_id int EXECUTE @distproc @distributor OUTPUT, @distribution_db OUTPUT, @loc_directory OUTPUT, @loc_account OUTPUT, @loc_mindistretention OUTPUT, @loc_maxdistretention OUTPUT, @loc_historyretention OUTPUT, @loc_historycleanupagent OUTPUT, @loc_distribcleanupagent OUTPUT, @@SERVERNAME, @local = 'local' IF @@error <> 0 OR @retcode <> 0 OR @distribution_db is NULL BEGIN RAISERROR (21007,16,-1) GOTO UNDO END /* Activate the dist publisher at the remote distributor */ SELECT @distproc = 'repl_distributor.master.dbo.sp_changedistpublisher' EXECUTE @retcode = @distproc @@SERVERNAME, 'active','true' IF @@error <> 0 OR @retcode <> 0 BEGIN GOTO UNDO END END ELSE /* set the registry */ BEGIN EXEC @retcode = dbo.sp_MScreate_distributor_tables if @@error <> 0 or @retcode <> 0 goto UNDO declare @distributor_login sysname select @distributor_login = 'distributor_admin' -- Add publisher rpc login if not exists (select * from master..syslogins where loginname = @distributor_login) begin EXEC @retcode = dbo.sp_addlogin @loginame = @distributor_login, @passwd = @password if @@error <> 0 or @retcode <> 0 goto UNDO end else begin -- Change the password if the distributor is local EXEC @retcode = dbo.sp_password NULL, @password, 'distributor_admin' if @@error <> 0 or @retcode <> 0 goto UNDO end -- Add the login to sysadmin -- Refer to sp_MSpublication_access in distribution db if is_srvrolemember('sysadmin', @distributor_login) <> 1 begin exec @retcode = dbo.sp_addsrvrolemember @distributor_login, 'sysadmin' IF @@error <> 0 OR @retcode <> 0 GOTO UNDO end -- Add Replication Agent Checkup Agent exec @retcode = dbo.sp_MScreate_replication_checkup_agent @heartbeat_interval = @heartbeat_interval if @@error <> 0 or @retcode <> 0 goto UNDO delete msdb..MSdistributor where property = 'heartbeat_interval' if @@error <> 0 goto UNDO insert into msdb..MSdistributor (property, value) values ('heartbeat_interval', convert(nvarchar(10), @heartbeat_interval)) if @@error <> 0 goto UNDO -- Add Replication Alerts and Response Jobs exec @retcode = dbo.sp_MSadd_distributor_alerts_and_responses if @@error <> 0 or @retcode <> 0 goto UNDO END /* ** Set the server option to indicate that this is a distributor. ** */ EXECUTE @retcode = dbo.sp_serveroption 'repl_distributor', 'dist', true IF @@error <> 0 OR @retcode <> 0 BEGIN GOTO UNDO END -- Set sp_MSrepl_startup to be a startup stored procedure -- Note: This needs to be after the marking the distribution server exec @retcode = dbo.sp_procoption 'sp_MSrepl_startup', 'startup', 'true' if @@error <> 0 or @retcode <> 0 goto UNDO1 exec @retcode = dbo.sp_MSrepl_startup if @@error <> 0 or @retcode <> 0 goto UNDO1 RETURN (0) UNDO1: exec dbo.sp_serveroption 'repl_distributor', 'dist', false UNDO: IF @server_added = 1 begin -- Drop the remote logins, otherwise, sp_dropserver will fail. EXECUTE dbo.sp_dropserver 'repl_distributor', 'droplogins' end RETURN (1) GO -------------------------------------------------------------------------------- --. sp_changedistributiondb -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_changedistributiondb') drop procedure sp_changedistributiondb go raiserror('Creating procedure sp_changedistributiondb', 0,1) go CREATE PROCEDURE sp_changedistributiondb ( @database sysname, @property sysname = NULL, /* The property to change */ @value nvarchar(255) = NULL /* The new property value */ ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @distributor sysname DECLARE @min_distretention int DECLARE @max_distretention int DECLARE @retcode int DECLARE @new_min_distretention int DECLARE @new_max_distretention int DECLARE @new_history_retention int DECLARE @agentname nvarchar(100) DECLARE @command nvarchar(255) DECLARE @security_mode int DECLARE @distbit int SELECT @distbit = 16 /* ** Parameter Check: @property. ** If the @property parameter is NULL, print the options. */ IF @property IS NULL BEGIN CREATE TABLE #tab1 (properties sysname NOT NULL) INSERT INTO #tab1 VALUES ('min_distretention') INSERT INTO #tab1 VALUES ('max_distretention') INSERT INTO #tab1 VALUES ('history_retention') SELECT * FROM #tab1 RETURN (0) END /* ** Parameter Check: @property. ** Check to make sure that @property is a valid property in ** sysarticles. */ IF @property IS NULL OR LOWER(@property) NOT IN ('min_distretention', 'max_distretention', 'history_retention') BEGIN RAISERROR (14115, 16, -1, '''min_distretention'', ''max_distretention'' or ''history_retention''') RETURN (1) END /* ** Check to make sure this is a distributor */ IF NOT EXISTS (SELECT * FROM master..sysservers WHERE UPPER(datasource) = UPPER(@@SERVERNAME) AND srvstatus & 8 <> 0) BEGIN RAISERROR (14114, 16, -1, @@SERVERNAME) RETURN(1) END /* ** Check if database is configured as a distributor database */ IF NOT EXISTS (SELECT * FROM master..sysdatabases WHERE name = @database AND category & @distbit <> 0) BEGIN RAISERROR (14117, 16, -1, @database) RETURN(1) END /* ** Change the property. */ IF LOWER(@property) = 'min_distretention' BEGIN IF @value IS NULL BEGIN RAISERROR (14043, 16, -1, '@value') RETURN (1) END /* ** Set the MinDistRetention registry key value */ SELECT @new_min_distretention = CONVERT(int, @value) /* ** Get MaxDistRetention value */ SELECT @max_distretention = max_distretention FROM msdb..MSdistributiondbs WHERE name = @database /* ** Check for invalid retention values */ IF @new_min_distretention < 0 BEGIN RAISERROR(14106, 16, -1) RETURN (1) END IF @new_min_distretention > @max_distretention BEGIN RAISERROR(14107, 16, -1) RETURN (1) END UPDATE msdb..MSdistributiondbs SET min_distretention = @new_min_distretention WHERE name = @database IF @@error <> 0 BEGIN RETURN (1) END /* ** Update Distribution Cleanup agent */ select @agentname = name from msdb..sysjobs j, msdb..sysjobsteps s where j.job_id = s.job_id and j.category_id = 11 and s.database_name = @database SELECT @command = 'EXEC dbo.sp_MSdistribution_cleanup @min_distretention = ' + CONVERT(nvarchar(12), @new_min_distretention) + ', @max_distretention = ' + CONVERT(nvarchar(12), @max_distretention) EXEC @retcode = msdb.dbo.sp_update_jobstep @job_name = @agentname, @step_id = 1, @command = @command IF @@error <> 0 OR @retcode <> 0 RETURN(1) END IF LOWER(@property) = 'max_distretention' BEGIN IF @value IS NULL BEGIN RAISERROR (14043, 16, -1, '@value') RETURN (1) END /* ** Set the MaxDistRetention registry key value */ SELECT @new_max_distretention = CONVERT(int, @value) /* ** Get MinDistRetention value */ SELECT @min_distretention = min_distretention FROM msdb..MSdistributiondbs WHERE name = @database /* ** Check for invalid retention values */ IF @new_max_distretention < 0 BEGIN RAISERROR(14106, 16, -1) RETURN (1) END IF @new_max_distretention < @min_distretention BEGIN RAISERROR(14107, 16, -1) RETURN (1) END UPDATE msdb..MSdistributiondbs SET max_distretention = @new_max_distretention WHERE name = @database IF @@error <> 0 BEGIN RETURN (1) END /* ** Update Distribution Cleanup agent */ select @agentname = name from msdb..sysjobs j, msdb..sysjobsteps s where j.job_id = s.job_id and j.category_id = 11 and s.database_name = @database SELECT @command = 'EXEC dbo.sp_MSdistribution_cleanup @min_distretention = ' + CONVERT(nvarchar(12), @min_distretention) + ', @max_distretention = ' + CONVERT(nvarchar(12), @new_max_distretention) EXEC @retcode = msdb.dbo.sp_update_jobstep @job_name = @agentname, @step_id = 1, @command = @command IF @@error <> 0 OR @retcode <> 0 RETURN(1) END IF LOWER(@property) = 'history_retention' BEGIN IF @value IS NULL BEGIN RAISERROR (14043, 16, -1, '@value') RETURN (1) END /* ** Set the HistoryRetention registry key value */ SELECT @new_history_retention = CONVERT(int, @value) UPDATE msdb..MSdistributiondbs SET history_retention = @new_history_retention WHERE name = @database IF @@error <> 0 BEGIN RETURN (1) END /* ** Update History Cleanup agent */ select @agentname = name from msdb..sysjobs j, msdb..sysjobsteps s where j.job_id = s.job_id and j.category_id = 12 and s.database_name = @database SELECT @command = 'EXEC dbo.sp_MShistory_cleanup @history_retention = ' + CONVERT(nvarchar(12), @new_history_retention) EXEC @retcode = msdb.dbo.sp_update_jobstep @job_name = @agentname, @step_id = 1, @command = @command IF @@error <> 0 OR @retcode <> 0 RETURN(1) END /* ** Return succeed. */ RAISERROR (14105, 10, -1, @property) RETURN (0) go -------------------------------------------------------------------------------- --. sp_dropdistributiondb -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_dropdistributiondb') drop procedure sp_dropdistributiondb go raiserror('Creating procedure sp_dropdistributiondb', 0,1) go CREATE PROCEDURE sp_dropdistributiondb ( @database sysname ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @retcode int DECLARE @agentname nvarchar(100) DECLARE @reg_key nvarchar(255) DECLARE @security_mode int DECLARE @distbit int DECLARE @distpublisher sysname DECLARE @distdb sysname DECLARE @device_name sysname DECLARE @command nvarchar(255) SELECT @distbit = 16 /* ** Check to make sure this is a distributor */ IF NOT EXISTS (SELECT * FROM master..sysservers WHERE UPPER(datasource) = UPPER(@@SERVERNAME) AND srvstatus & 8 <> 0) BEGIN RAISERROR (14114, 16, -1, @@SERVERNAME) RETURN(1) END /* ** Check if database is configured as a distributor database */ IF NOT EXISTS (SELECT * FROM msdb..MSdistributiondbs WHERE name = @database) BEGIN RAISERROR (14117, 16, -1, @database) RETURN(1) END /* ** Check if any DistPublishers are using this database */ IF EXISTS (SELECT * FROM msdb..MSdistpublishers WHERE distribution_db = @database) BEGIN RAISERROR (14120, 16, -1, @database) RETURN (1) END /* ** Check if the DB is being currently used */ IF EXISTS (SELECT * FROM master..sysprocesses WHERE dbid = DB_ID(@database)) BEGIN RAISERROR (21122, 16, 1, @database) RETURN (1) END /* ** Drop the history cleanup agent. */ -- Get agent name select @agentname = null select @agentname = name from msdb..sysjobs j, msdb..sysjobsteps s where j.job_id = s.job_id and j.category_id = 12 and s.database_name = @database if @agentname is not null BEGIN EXEC @retcode = msdb.dbo.sp_delete_job @job_name = @agentname IF @@ERROR <> 0 or @retcode <> 0 BEGIN RETURN(1) END END /* ** Drop the distribution cleanup agent. */ select @agentname = null select @agentname = name from msdb..sysjobs j, msdb..sysjobsteps s where j.job_id = s.job_id and j.category_id = 11 and s.database_name = @database if @agentname is not null BEGIN EXEC @retcode = msdb.dbo.sp_delete_job @job_name = @agentname IF @@ERROR <> 0 or @retcode <> 0 BEGIN RETURN(1) END END /* ** Update sysdatabase category bit before dropping the database ** Otherwise, the database can not be dropped. ** */ UPDATE master..sysdatabases SET category = category & ~@distbit WHERE name = @database IF @@ERROR <> 0 BEGIN RETURN (1) END -- Drop the distributor db if it exists IF EXISTS (SELECT * FROM master..sysdatabases WHERE name = @database) BEGIN CREATE TABLE #db_existed ( db_existed bit NOT NULL ) /* Get version stamp */ SELECT @command = 'INSERT INTO #db_existed SELECT db_existed FROM ' + QUOTENAME(@database) + '..MSrepl_version' EXEC(@command) IF @@ERROR <> 0 BEGIN RETURN(1) END -- Drop the distribution db only if it is created in sp_adddistributiondb. IF NOT EXISTS (SELECT * FROM #db_existed where db_existed = 0x1) BEGIN -- we're dropping the database, so don't bother to clean up -- individual records. Just make sure we blow away the synchronization -- files & directories hosted by the file system. SELECT @command = QUOTENAME(@database) + '.dbo.sp_MSdrop_snapshot_dirs' SELECT @command = 'EXEC ' + @command EXEC (@command) IF (@@ERROR <> 0) BEGIN RETURN (1) END /* Save the device info before dropping the database */ CREATE TABLE #distdbdevices (name sysname NOT NULL) /* Drop distributor devices */ /* Query is copied from sp_helpdb */ SELECT @command = 'INSERT INTO #distdbdevices select DISTINCT name from ' + QUOTENAME(@database) + '.dbo.sysfiles' EXEC (@command) IF @@ERROR <>0 BEGIN RETURN(1) END /* ** Drop the distribution database */ SELECT @command = 'drop database ' + QUOTENAME(@database) EXEC (@command) IF @@ERROR <> 0 BEGIN /* Mark the database as distribution database again ** Otherwise, this sp will fail when it is reentered. ** It is often the case that if there's an open session ** on the database, it can not be dropped. */ RETURN(1) END /* Drop distributor devices */ /* Query is copied from sp_helpdb */ /* SQL SERVER 7.0 may drop some auto generated device files, drop drop them here again */ DECLARE hCdropdistributiondb CURSOR LOCAL FAST_FORWARD FOR SELECT DISTINCT dd.name FROM #distdbdevices dd, master.dbo.sysdevices ss WHERE ss.name = dd.name FOR READ ONLY OPEN hCdropdistributiondb FETCH hCdropdistributiondb INTO @device_name WHILE (@@fetch_status <> -1) BEGIN /* ** Device may be used by other databases ** Ignore all errors */ EXEC dbo.sp_dropdevice @device_name, DELFILE FETCH hCdropdistributiondb INTO @device_name END CLOSE hCdropdistributiondb DEALLOCATE hCdropdistributiondb END -- else, database did exist before it was made the distributor, -- do full cleanup ELSE BEGIN -- run 'fast clean' routine first. this removes repldata files -- and truncates MSrepl_transactions/commands SELECT @command = QUOTENAME(@database) + '.dbo.sp_MSfast_delete_trans' SELECT @command = 'EXEC ' + @command EXEC (@command) IF (@@ERROR <> 0) BEGIN RETURN (1) END -- Do distribution cleanup the final time -- this handles those fiddly agent tables & such -- ( and would delete commands/xacts if we hadn't already purged 'em ) SELECT @command = QUOTENAME(@database) + '.dbo.sp_MSdistribution_cleanup @min_distretention = 0, @max_distretention = 0' SELECT @command = 'EXEC ' + @command EXEC (@command) IF (@@ERROR <> 0) BEGIN RETURN (1) END END END /* ** Delete the DistributionDB entry */ DELETE msdb.dbo.MSdistributiondbs where name = @database IF @@error <> 0 BEGIN RETURN(1) END RETURN (0) GO -------------------------------------------------------------------------------- --. sp_MSupdate_replication_status -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSupdate_replication_status') drop procedure sp_MSupdate_replication_status go raiserror('Creating procedure sp_MSupdate_replication_status', 0,1) go create procedure sp_MSupdate_replication_status @publisher sysname, @publisher_db sysname, @publication sysname, @publication_type int = 0, -- 0 Transactional/Snapshot 1 Merge @agent_type int, @agent_name nvarchar(100), @status int as declare @deleted int declare @refresh int declare @getstatus int declare @dummy int set @deleted = -1 set @refresh = -2 -- Status used to only update the timestamp column set @getstatus = -3 -- Get status of agent for dummy distribution row if (select object_id('tempdb.dbo.MSreplication_agent_status')) is NULL return 0 if @status = @getstatus begin select @status = isnull(status, 0) from tempdb.dbo.MSreplication_agent_status where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = 'ALL' and agent_type = @agent_type end -- Update timestamp column via dummy update if @status = @refresh begin -- Dummy update to force timestamps to be updated. update tempdb.dbo.MSreplication_agent_status set status = status where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication like @publication -- Must use like as publication may be "%" return (0) end -- Remove row if @deleted if @status = @deleted begin if @@trancount > 0 begin if exists (select * from tempdb.dbo.MSreplication_agent_status with (TABLOCKX) where 1 = 1) begin select @dummy = 1 end end if @agent_name = '%' delete from tempdb.dbo.MSreplication_agent_status with (TABLOCKX) where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and agent_type = @agent_type else if @agent_name = NULL -- Special case when all agents of the type are dropped delete from tempdb.dbo.MSreplication_agent_status with (TABLOCKX) where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and agent_type = @agent_type else delete from tempdb.dbo.MSreplication_agent_status with (TABLOCKX) where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and agent_type = @agent_type and agent_name = @agent_name -- Dummy update to force timestamps to be updated. This will signal a row has been -- removed. update tempdb.dbo.MSreplication_agent_status set status = status where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication return (0) end -- If misc. replication job then the status needs to be mapped. if @agent_type = 5 begin set @status = case isnull(@status,5) -- mapped to never run when 0 then 6 -- Fail mapping when 1 then 2 -- Success mapping when 2 then 5 -- Retry mapping when 3 then 2 -- Shutdown mapping when 4 then 3 -- Inprogress mapping when 5 then 0 -- Unknown is mapped to never run end end if not exists (select * from tempdb.dbo.MSreplication_agent_status with (NOLOCK) where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication and agent_type = @agent_type and agent_name = @agent_name) begin if @@trancount > 0 begin if exists (select * from tempdb.dbo.MSreplication_agent_status with (TABLOCKX) where 1 = 1) begin select @dummy = 1 end end insert into tempdb.dbo.MSreplication_agent_status (publisher, publisher_db, publication, publication_type, agent_type, status, agent_name) values (@publisher, @publisher_db, @publication, @publication_type, @agent_type, @status, @agent_name) -- Dummy update to force timestamps to be updated. This will signal a row has been -- added. update tempdb.dbo.MSreplication_agent_status set status = status where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication end else begin update tempdb.dbo.MSreplication_agent_status set status = @status where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and (publication = @publication or @publication = 'ALL')and agent_type = @agent_type and agent_name = @agent_name end return (0) go -------------------------------------------------------------------------------- --. sp_MSenum_misc_agents -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSenum_misc_agents') drop procedure sp_MSenum_misc_agents go raiserror('Creating procedure sp_MSenum_misc_agents', 0,1) go create procedure sp_MSenum_misc_agents as SET NOCOUNT ON declare @timestamp timestamp -- Not supported, but returned to be consistent with other sp_MSenum_replication_agent -- result set. set @timestamp = 0 select j.name, 'agent_type' = c.name, 'status' = case isnull(jh.run_status, 5) -- mapped to never run when 0 then 6 -- Fail mapping when 1 then 2 -- Success mapping when 2 then 5 -- Retry mapping when 3 then 2 -- Shutdown mapping when 4 then 3 -- Inprogress mapping when 5 then 0 -- Unknown is mapped to never run end, jh.message, 'start_time' = convert(nvarchar(8), jh.run_date) + N' ' + stuff(stuff(right(convert(nvarchar(7), jh.run_time + 1000000), 6), 5, 0, N':'), 3, 0, N':') + + N'.000', jh.run_duration, 'job_id' = convert(binary(16), j.job_id), 'local_timestamp' = @timestamp from msdb..sysjobs j LEFT OUTER JOIN msdb..sysjobhistory jh ON j.job_id = jh.job_id and jh.instance_id = (select max(instance_id) from msdb..sysjobhistory jh2 where jh2.job_id = j.job_id) INNER JOIN msdb..syscategories c ON j.category_id = c.category_id where j.category_id in (11, 12,16,17,18) order by j.job_id asc go -------------------------------------------------------------------------------- --. sp_MSrepl_startup -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSrepl_startup') drop procedure sp_MSrepl_startup go raiserror('Creating procedure sp_MSrepl_startup', 0,1) go create proc sp_MSrepl_startup as -- Drop and create publisher side cache table if exists (select * from tempdb..sysobjects where name = 'MSpublisher_access' and type = 'U') drop table tempdb.dbo.MSpublisher_access create table tempdb.dbo.MSpublisher_access ( spid int NOT NULL, db_id int not null, publication sysname not null, login_time datetime not null, pubid uniqueidentifier null -- Used for merge only. ) CREATE UNIQUE CLUSTERED INDEX ucMSpublisher_access ON tempdb.dbo.MSpublisher_access (spid, publication, db_id, login_time) -- Drop and create distributor side cache table -- We need to avoid publisher and distributor using the same table to prevent -- contention in local distributor case. if exists (select * from master..sysservers WHERE srvstatus & 8 <> 0 and UPPER(datasource) = UPPER(@@servername)) begin if exists (select * from tempdb..sysobjects where name = 'MSdistributor_access' and type = 'U') drop table tempdb.dbo.MSdistributor_access create table tempdb.dbo.MSdistributor_access ( spid int NOT NULL, db_id int not null, agent_id int not null, agent_type int not null, publication_id int not null, login_time datetime not null ) CREATE UNIQUE CLUSTERED INDEX ucMSdistributor_access ON tempdb.dbo.MSdistributor_access (spid, agent_id, db_id, login_time) end go -- If a distributor is installed, mark the sp as a startup sp. if exists (select * FROM master..sysservers WHERE srvstatus & 8 <> 0) exec dbo.sp_procoption 'sp_MSrepl_startup', 'startup', 'true' go -------------------------------------------------------------------------------- --. sp_MSfix_6x_tasks -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSfix_6x_tasks') drop procedure sp_MSfix_6x_tasks go raiserror('Creating procedure sp_MSfix_6x_tasks', 0,1) go CREATE PROCEDURE sp_MSfix_6x_tasks ( @publisher sysname = NULL ) AS SET NOCOUNT ON DECLARE @distributor sysname DECLARE @distproc nvarchar (255) declare @retcode int -- If @publisher is null redirect the call to distributor if @publisher is null begin /* ** Get distribution server information for remote RPC ** agent verification. */ EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT IF @@error <> 0 OR @retcode <> 0 BEGIN RAISERROR (14071, 16, -1) RETURN (1) END /* ** RPC distributor */ SELECT @distproc = RTRIM(@distributor) + '.master.dbo.sp_MSfix_6x_tasks' EXECUTE @retcode = @distproc @publisher = @@SERVERNAME IF @@ERROR <> 0 or @retcode <> 0 return (1) end else begin declare @category_id int declare @category_name sysname declare @server sysname declare @databasename sysname declare @name sysname declare @distdb sysname declare @job_id uniqueidentifier declare @sSubsystem sysname -- Drop entry in systasks first. DECLARE hCtasks CURSOR LOCAL FAST_FORWARD FOR SELECT name FROM msdb.dbo.systasks_view st WHERE -- drop distribution agents. (st.name LIKE @publisher + '_' + '%' + '_' + '%' AND LOWER(subsystem) = 'distribution' AND server = @@SERVERNAME) OR (LOWER(subsystem) = 'logreader' AND server = @publisher) OR (LOWER(subsystem) = 'snapshot' AND server = @publisher) OR (st.name LIKE '%' + '_' + '%' + '_Cleanup' AND st.command LIKE '%' + 'sp_replcleanup' + '%' AND LOWER(subsystem) = 'tsql') FOR READ ONLY OPEN hCtasks FETCH hCtasks INTO @name WHILE (@@fetch_status <> -1) BEGIN EXEC @retcode = msdb.dbo.sp_droptask @name = @name if @retcode <> 0 or @@error <> 0 return(1) FETCH hCtasks INTO @name END -- Now spin through each old replication job and fixup categories names declare hcJobsToFix CURSOR LOCAL FAST_FORWARD for select distinct j.job_id, j.name, s.subsystem, s.server, s.database_name from msdb.dbo.sysjobs j left join msdb.dbo.sysjobsteps s on j.job_id = s.job_id where j.category_id = 0 and s.step_id = 1 and lower(s.subsystem) in ( 'snapshot', 'logreader', 'distribution' ) for read only open hcJobsToFix fetch hcJobsToFix into @job_id, @name, @sSubsystem, @server,@databasename while (@@fetch_status <> -1 ) begin -- Note, have to make it a transaction, once the category_id is changed, -- the task will never be picked up again. begin tran -- Get Distribution category name (assumes category_id = 10) select @category_id = case lower(@sSubsystem) when 'snapshot' then 15 when 'distribution' then 10 when 'logreader' then 13 else 0 end select @category_name = name FROM msdb.dbo.syscategories where category_id = @category_id -- raiserror( 'Would update %s to category %d based on subsystem value %s', -1, 10, @nJobName, @iCategory, @sSubsystem ) exec @retcode = msdb.dbo.sp_update_job @job_id = @job_id, @category_name = @category_name if @retcode <> 0 or @@error <> 0 goto UNDO -- Add the replication agent for monitoring SELECT @distdb = distribution_db from msdb..MSdistpublishers where UPPER(name) = UPPER(@server) IF (@category_id = 13) -- Logreader BEGIN SELECT @distproc = @distdb + '.dbo.sp_MSadd_logreader_agent' EXECUTE @retcode = @distproc @name = @name, @publisher = @server, @publisher_db = @databasename, @publication = '', @local_job = 1, @job_existing = 1, @job_id = @job_id IF (@retcode <> 0 or @@error<>0) goto UNDO END ELSE IF (@category_id = 15) -- Snapshot BEGIN DECLARE @publication sysname SELECT @publication = NULL EXECUTE master.dbo.sp_MSget_publication_from_taskname @taskname = @name, @publisher = @server, @publisherdb = @databasename, @publication = @publication OUTPUT IF (@publication IS NOT NULL ) BEGIN SELECT @distproc = @distdb + '.dbo.sp_MSadd_snapshot_agent' EXECUTE @retcode = @distproc @name = @name, @publisher = @server, @publisher_db = @databasename, @publication = @publication, @local_job = 1, @job_existing = 1, @snapshot_jobid = @job_id IF (@retcode <> 0 or @@error<>0) goto UNDO SELECT @distproc = @distdb + '.dbo.sp_MSadd_publication' EXECUTE @retcode = @distproc @publisher = @server, @publisher_db = @databasename, @publication = @publication, @publication_type = 0 -- Transactional IF (@retcode <> 0 or @@error<>0) goto UNDO END END commit tran fetch hcJobsToFix into @job_id, @name, @sSubsystem, @server,@databasename end close hcJobsToFix deallocate hcJobsToFix end return (0) UNDO: if @@trancount <> 0 rollback tran return (1) GO -------------------------------------------------------------------------------- --. Update permissions on sp_MSenum_replication_job -------------------------------------------------------------------------------- grant execute on sp_MSenum_replication_job to public go -------------------------------------------------------------------------------- --. Tran repl objects (repltran.sql) -------------------------------------------------------------------------------- dump tran master with no_log go -------------------------------------------------------------------------------- --. sp_MSdrop_repltran -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSdrop_repltran') drop procedure sp_MSdrop_repltran go raiserror('Creating procedure sp_MSdrop_repltran', 0,1) go create procedure sp_MSdrop_repltran as if exists( select * from sysobjects where type = 'P ' and name = 'sp_MSsetfilterparent' ) drop procedure sp_MSsetfilterparent if exists( select * from sysobjects where type = 'P ' and name = 'sp_MSdoesfilterhaveparent' ) drop procedure sp_MSdoesfilterhaveparent if exists( select * from sysobjects where type = 'P ' and name = 'sp_MSsetfilteredstatus' ) drop procedure sp_MSsetfilteredstatus if exists ( select * from sysobjects where type = 'P ' and name = 'sp_MSreplsup_table_has_pk' ) DROP PROC sp_MSreplsup_table_has_pk if exists (select * from sysobjects where type = 'P ' and name = 'sp_MScreate_pub_tables') drop procedure sp_MScreate_pub_tables if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSdrop_expired_subscription') drop procedure sp_MSdrop_expired_subscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_replsync') drop procedure sp_replsync if exists (select * from sysobjects where type = 'P ' and name = 'sp_enumfullsubscribers') drop procedure sp_enumfullsubscribers if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSaddexecarticle') drop procedure sp_MSaddexecarticle if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_validate_subscription') drop procedure sp_MSscript_validate_subscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSvalidate_subscription') drop procedure sp_MSvalidate_subscription dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_addarticle') drop procedure sp_addarticle if exists (select * from sysobjects where type = 'P ' and name = 'sp_articlecolumn') drop procedure sp_articlecolumn dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_articlefilter') drop procedure sp_articlefilter if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSarticletextcol') drop procedure sp_MSarticletextcol dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_MStextcolstatus') drop procedure sp_MStextcolstatus if exists (select * from sysobjects where type = 'P ' and name = 'sp_articleview') drop procedure sp_articleview dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_addpublication') drop procedure sp_addpublication dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_addsubscription') drop procedure sp_addsubscription IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P ' AND name = 'sp_changearticle') DROP PROCEDURE sp_changearticle dump tran master with no_log IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P ' AND name = 'sp_changepublication') DROP PROCEDURE sp_changepublication IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P ' AND name = 'sp_changesubscription') DROP PROCEDURE sp_changesubscription dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_MShcchangesubstatus1') drop procedure sp_MShcchangesubstatus1 if exists (select * from sysobjects where type = 'P ' and name = 'sp_MShcchangesubstatus2') drop procedure sp_MShcchangesubstatus2 if exists (select * from sysobjects where type = 'P ' and name = 'sp_MShcchangesubstatus3') drop procedure sp_MShcchangesubstatus3 dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_changesubstatus') drop procedure sp_changesubstatus if exists (select * from sysobjects where type = 'P ' and name = 'sp_droparticle') drop procedure sp_droparticle dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_droppublication') drop procedure sp_droppublication if exists (select * from sysobjects where type = 'P ' and name = 'sp_dropsubscription') drop procedure sp_dropsubscription dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_helparticle') drop procedure sp_helparticle dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_helparticlecolumns') drop procedure sp_helparticlecolumns if exists (select * from sysobjects where type = 'P ' and name = 'sp_helppublication') drop procedure sp_helppublication if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSaddpub_snapshot') drop procedure sp_MSaddpub_snapshot dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_helpsubscription') drop procedure sp_helpsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_subscribe') drop procedure sp_subscribe if exists (select * from sysobjects where type = 'P ' and name = 'sp_unsubscribe') drop procedure sp_unsubscribe if exists (select * from sysobjects where type = 'P ' and name = 'sp_refreshsubscriptions') drop procedure sp_refreshsubscriptions dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSpublishdb') drop procedure sp_MSpublishdb if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSactivate_auto_sub') drop procedure sp_MSactivate_auto_sub if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSget_synctran_commands') drop procedure sp_MSget_synctran_commands if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSdrop_pub_tables') begin -- Don't drop the system tables here. repltran.sql should not -- delete any data in the master database (see bug 34219). -- exec dbo.sp_MSdrop_pub_tables drop procedure sp_MSdrop_pub_tables end -- SyncTran if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSis_col_replicated') drop procedure sp_MSis_col_replicated if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSis_pk_col') drop procedure sp_MSis_pk_col if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_insert_statement') drop procedure sp_MSscript_insert_statement if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_update_statement') drop procedure sp_MSscript_update_statement if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_delete_statement') drop procedure sp_MSscript_delete_statement if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_beginproc') drop procedure sp_MSscript_beginproc if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_security') drop procedure sp_MSscript_security if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_endproc') drop procedure sp_MSscript_endproc if exists (select * from sysobjects where type = 'P ' and name = 'sp_MStable_not_modifiable') drop procedure sp_MStable_not_modifiable if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_sync_ins_proc') drop procedure sp_MSscript_sync_ins_proc if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_sync_upd_proc') drop procedure sp_MSscript_sync_upd_proc if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_sync_del_proc') drop procedure sp_MSscript_sync_del_proc if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSgen_sync_tran_procs') drop procedure sp_MSgen_sync_tran_procs if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSmark_proc_norepl') drop procedure sp_MSmark_proc_norepl if exists (select * from sysobjects where type = 'P ' and name = 'sp_articlesynctranprocs') drop procedure sp_articlesynctranprocs if exists (select * from sysobjects where type = 'P ' and name = 'sp_reinitsubscription') drop procedure sp_reinitsubscription dump tran master with no_log if exists( select * from sysobjects where type = 'P ' and name = N'sp_getarticlepkcolbitmap') begin drop procedure sp_getarticlepkcolbitmap end if exists( select * from sysobjects where type = 'P ' and name = N'sp_gettypestring' ) begin drop procedure sp_gettypestring end if exists( select * from sysobjects where type = 'P ' and name = N'sp_isarticlecolbitset' ) begin drop procedure sp_isarticlecolbitset end if exists( select * from sysobjects where type = 'P ' and name = N'sp_scriptpkwhereclause' ) begin drop procedure sp_scriptpkwhereclause end if exists( select * from sysobjects where type = 'P ' and name = N'sp_scriptupdateparams' ) begin drop procedure sp_scriptupdateparams end if exists( select * from sysobjects where type = 'P ' and name = N'sp_scriptinsproc' ) begin drop procedure sp_scriptinsproc end if exists( select * from sysobjects where type = 'P ' and name = N'sp_scriptdelproc' ) begin drop procedure sp_scriptdelproc end if exists( select * from sysobjects where type = 'P ' and name = N'sp_scriptupdproc' ) begin drop procedure sp_scriptupdproc end if exists ( select * from sysobjects where type = 'P ' and name = 'sp_scriptmappedupdproc' ) begin drop procedure sp_scriptmappedupdproc end if exists ( select * from sysobjects where type = 'P ' and name = 'sp_fetchshowcmdsinput' ) begin drop procedure sp_fetchshowcmdsinput end if exists ( select * from sysobjects where type = 'P ' and name = 'sp_replshowcmds' ) begin drop procedure sp_replshowcmds end if exists ( select * from sysobjects where type = 'P ' and name = 'sp_publication_validation' ) begin drop procedure sp_publication_validation end if exists ( select * from sysobjects where type = 'P ' and name = 'sp_article_validation' ) begin drop procedure sp_article_validation end if exists ( select * from sysobjects where type = 'P ' and name = 'sp_MSdrop_6x_replication_agent' ) begin drop procedure sp_MSdrop_6x_replication_agent end if exists ( select * from sysobjects where type = 'P ' and name = 'sp_script_synctran_commands' ) begin drop procedure sp_script_synctran_commands end dump tran master with no_log go -------------------------------------------------------------------------------- --. sp_MSscript_validate_subscription -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSscript_validate_subscription') drop procedure sp_MSscript_validate_subscription go raiserror('Creating procedure sp_MSscript_validate_subscription', 0,1) go create procedure sp_MSscript_validate_subscription @publication sysname, @article sysname as declare @pubid int declare @artid int select @pubid = pubid from syspublications where name = @publication select @artid = artid from sysarticles where pubid = @pubid and name = @article insert into #proctext(procedure_text) values (N'exec @retcode = dbo.sp_MSvalidate_subscription @orig_server, @orig_db, ' + convert(nvarchar(10), @artid)) insert into #proctext(procedure_text) values (N'if @@error <> 0 or @retcode <> 0 return -1 ' ) go grant execute on dbo.sp_MSscript_validate_subscription to public go -------------------------------------------------------------------------------- --. sp_MSvalidate_subscription -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSvalidate_subscription') drop procedure sp_MSvalidate_subscription go raiserror('Creating procedure sp_MSvalidate_subscription', 0,1) go create procedure sp_MSvalidate_subscription @subscriber sysname, @subscriber_db sysname, @artid int as declare @srvid smallint select @srvid = srvid from master..sysservers where srvname = @subscriber if not exists (select * from syssubscriptions where artid = @artid and srvid = @srvid and dest_db = @subscriber_db) begin -- The subscription has been dropped from the publisher. Please run sp_subscription_cleanup to cleanup the triggers. exec sp_MSreplraiserror 21161 return -1 end go grant execute on dbo.sp_MSvalidate_subscription to public go -------------------------------------------------------------------------------- --. sp_addpublication -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_addpublication') drop procedure sp_addpublication go raiserror('Creating procedure sp_addpublication', 0,1) go CREATE PROCEDURE sp_addpublication ( @publication sysname, /* publication name */ @taskid int = 0, /* backward compatible */ @restricted nvarchar (10) = 'false', /* publication security */ @sync_method nvarchar(13) = 'native', /* (bcp) native, (bcp) character */ @repl_freq nvarchar(10) = 'continuous', /* continuous, snapshot */ @description nvarchar (255) = NULL, /* publication description */ @status nvarchar(8) = 'inactive', /* publication status; 0=inactive, 1=active */ @independent_agent nvarchar(5) = 'false', /* true or false */ @immediate_sync nvarchar(5) = 'false', /* true or false */ @enabled_for_internet nvarchar(5) = 'false', /* true or false */ @allow_push nvarchar(5) = 'true', /* true or false */ @allow_pull nvarchar(5) = 'false', /* true or false */ @allow_anonymous nvarchar(5) = 'false', /* true or false */ -- SyncTran @allow_sync_tran nvarchar(5) = 'false', /* true or false */ @autogen_sync_procs nvarchar(5) = 'true', /* auto gen sync tran procs per article */ @retention int = 72 /* over weekend - 3 days */ ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @retcode int /* return code value for procedure execution */ DECLARE @rfid tinyint /* identifier for replication frequency */ DECLARE @publish_bit smallint /* publication bit (flag) in sysobjects */ DECLARE @smid tinyint /* identifier for sync method */ DECLARE @statid tinyint /* status id based on @status */ DECLARE @subs_type_id tinyint /* subscription type id based on @subscription_type */ DECLARE @distributor sysname DECLARE @distribdb sysname DECLARE @distproc nvarchar (255) DECLARE @agentname nvarchar (40) DECLARE @dbname sysname DECLARE @mergepublish_bit smallint DECLARE @found int DECLARE @independent_agent_id bit DECLARE @immediate_sync_id bit DECLARE @enabled_for_internet_id bit DECLARE @allow_push_id bit DECLARE @allow_pull_id bit DECLARE @allow_anonymous_id bit DECLARE @pubid int declare @distgroup sysname -- SyncTran DECLARE @allow_sync_tran_id bit DECLARE @autogen_sync_procs_id bit select @allow_sync_tran_id = 0, @autogen_sync_procs_id = 0 -- end SyncTran declare @qv_replication varchar(10) declare @qv_replication_unlimited integer declare @qv_value_replication integer select @qv_replication = '2745196162', @qv_replication_unlimited = 0 /* ** The default value for TRAN publication is always 72 hours */ if @retention is NULL BEGIN RAISERROR(20081, 16, -1, 'retention') RETURN (1) END /* ** A @retention value of zero means an infinite retention period */ if @retention < 0 BEGIN RAISERROR (20050, 16, -1, 1) RETURN(1) END SELECT @publish_bit = 32 SELECT @mergepublish_bit = 4 /* ** 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 & 1 FROM master..sysdatabases WHERE name = DB_NAME()) = 0 BEGIN RAISERROR (14013, 16, -1) RETURN (1) END IF @taskid <> 0 BEGIN -- No longer supported RAISERROR (21023, 16, -1,'@taskid') 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 /* ** Check if the publication already exists. ** 1. Check transaction-level publications ** 2. Check merge publications */ IF EXISTS (SELECT * FROM syspublications WHERE name = @publication) BEGIN RAISERROR (14016, 16, -1, @publication) RETURN (1) END if (select category & @mergepublish_bit from master..sysdatabases where name = DB_NAME()) <> 0 begin EXEC @retcode = dbo.sp_helpmergepublication @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 /* ** Get distribution server information for remote RPC ** agent verification. */ 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 /* ** Parameter Check: @sync_method ** The synchronization method must be one of the following: ** ** 0 [bcp] native ** 1 [bcp] character */ SELECT @sync_method = LOWER(@sync_method) IF @sync_method IS NULL OR @sync_method NOT IN ('native', 'character', 'bcp native', 'bcp character') BEGIN RAISERROR (14014, 16, -1) RETURN (1) END IF @sync_method IN ('character', 'bcp character') SELECT @smid = 1 ELSE SELECT @smid = 0 /* ** Parameter Check: @repl_freq. ** Make sure that the replication frequency is one of the following: ** ** id frequency ** == ========== ** 0 continuous ** 1 snapshot */ SELECT @repl_freq = LOWER(@repl_freq) IF @repl_freq IS NULL OR @repl_freq NOT IN ('continuous', 'snapshot') BEGIN RAISERROR (14015, 16, -1) RETURN (1) END IF @repl_freq = 'snapshot' SELECT @rfid = 1 ELSE SELECT @rfid = 0 -- disable tran publishing on REPLICATION_LIMITED sku exec @qv_value_replication = master.dbo.xp_qv @qv_replication if (@rfid = 0) and ( @qv_value_replication != @qv_replication_unlimited ) begin raiserror(21108, 16, -1) return (1) end /* ** Parameter Check: @restricted. */ IF (@restricted IS NULL) OR (LOWER(@restricted) NOT IN ('true', 'false')) BEGIN RAISERROR (14017, 16, -1) RETURN (1) END /* ** Restricted publications are no longer supported */ IF LOWER(@restricted) = 'true' BEGIN RAISERROR (14147, 16, -1) RETURN(1) END /* ** Parameter Check: @status. ** The @status value can be: ** ** statid status ** ====== ======== ** 0 inactive ** 1 active */ IF @status IS NULL OR LOWER(@status) NOT IN ('inactive', 'active') BEGIN RAISERROR (14012, 16, -1) RETURN (1) END IF LOWER(@status) = 'active' SELECT @statid = 1 ELSE SELECT @statid = 0 /* ** Parameter Check: @independent_agent. */ IF @independent_agent IS NULL OR LOWER(@independent_agent) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@independent_agent') RETURN (1) END IF LOWER(@independent_agent) = 'true' SELECT @independent_agent_id = 1 ELSE SELECT @independent_agent_id = 0 /* ** Parameter Check: @immediate_sync. */ IF @immediate_sync IS NULL OR LOWER(@immediate_sync) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@immediate_sync') RETURN (1) END IF LOWER(@immediate_sync) = 'true' SELECT @immediate_sync_id = 1 ELSE SELECT @immediate_sync_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: @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 /* Immediate_sync publications have to be independent_agent */ IF @immediate_sync_id = 1 AND @independent_agent_id = 0 BEGIN RAISERROR (21022, 16, -1) RETURN (1) END /* ** Non-immediate sync do not support anonymous subscriptions. */ IF @immediate_sync_id = 0 AND @allow_anonymous_id = 1 BEGIN RAISERROR (20011, 16, -1) RETURN (1) END -- SyncTran /* ** Parameter Check: @allow_sync_tran */ IF @allow_sync_tran IS NULL OR LOWER(@allow_sync_tran) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@allow_sync_tran') RETURN (1) END IF LOWER(@allow_sync_tran) = 'true' BEGIN SELECT @allow_sync_tran_id = 1 --Parameter Check: @autogen_sync_procs IF @autogen_sync_procs IS NULL OR LOWER(@autogen_sync_procs) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@autogen_sync_procs') RETURN (1) END IF LOWER(@autogen_sync_procs) = 'true' SELECT @autogen_sync_procs_id = 1 ELSE SELECT @autogen_sync_procs_id = 0 END ELSE BEGIN SELECT @allow_sync_tran_id = 0 SELECT @autogen_sync_procs_id = 0 END -- end SyncTran /* ** 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 /* ** Add publication to syspublications. */ begin tran save TRAN sp_addpublication select @dbname = db_name() /* ** Construct Log Reader agent name. */ IF @rfid = 0 and NOT EXISTS (SELECT * FROM syspublications where repl_freq = 0) BEGIN /* ** Schedule Log Reader agent for the database */ SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb +'.dbo.sp_MSadd_logreader_agent' EXECUTE @retcode = @distproc @publisher = @@SERVERNAME, @publisher_db = @dbname, @publication = 'ALL', @local_job = 1 IF @@ERROR <> 0 or @retcode <> 0 GOTO UNDO END INSERT syspublications(description, name, repl_freq, status, sync_method, snapshot_jobid, independent_agent, immediate_sync, enabled_for_internet, allow_push, allow_pull, allow_anonymous, immediate_sync_ready, -- SyncTran allow_sync_tran, autogen_sync_procs, retention) VALUES (@description, @publication, @rfid, @statid, @smid, NULL, @independent_agent_id, @immediate_sync_id, @enabled_for_internet_id, @allow_push_id, @allow_pull_id, @allow_anonymous_id, 0, -- SyncTran @allow_sync_tran_id, @autogen_sync_procs_id, @retention) IF @@ERROR <> 0 BEGIN RAISERROR (14018, 16, -1) GOTO UNDO END SELECT @pubid = @@IDENTITY DECLARE @false bit SELECT @false = 0 DECLARE @null sysname SELECT @null = NULL /* ** Add the publication to the distributor side */ SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + '.dbo.sp_MSadd_publication' EXECUTE @retcode = @distproc @publisher = @@SERVERNAME, @publisher_db = @dbname, @publication = @publication, @publication_type = @rfid, @independent_agent = @independent_agent_id, @immediate_sync = @immediate_sync_id, @allow_push = @allow_push_id, @allow_pull = @allow_pull_id, @allow_anonymous = @allow_anonymous_id, @snapshot_agent = @null, @logreader_agent = @agentname, @description = @description, @retention = @retention IF @@ERROR <> 0 or @retcode <> 0 BEGIN GOTO UNDO 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 UNDO COMMIT TRAN RETURN(0) UNDO: IF @@TRANCOUNT > 0 begin ROLLBACK TRAN sp_addpublication COMMIT TRAN end return 1 go grant execute on dbo.sp_addpublication to public go -------------------------------------------------------------------------------- --. sp_articlecolumn -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_articlecolumn') drop procedure sp_articlecolumn go raiserror('Creating procedure sp_articlecolumn', 0,1) go CREATE PROCEDURE sp_articlecolumn ( @publication sysname, /* The publication name */ @article sysname, /* The article name */ @column sysname = NULL, /* The column name */ @operation nvarchar(4) = 'add' /* Add or delete a column */ -- synctran , @refresh_synctran_procs bit = 1 -- refresh synctran procs or not , @ignore_distributor bit = 0 ) AS /* ** Declarations. */ DECLARE @bit tinyint /* Bit offset */ --DECLARE @byte tinyint /* Byte offset */ DECLARE @word tinyint /* word offset */ DECLARE @cnt tinyint, @idx tinyint /* Loop counter, index */ DECLARE @columns binary(32) /* Temporary storage for the converted column */ DECLARE @mask binary(2) /* Bit mask to set the bit on */ DECLARE @mval int -- DECLARE @newbyte binary(1) /* New byte to replace old byte with */ -- DECLARE @oldbyte binary(1) /* Temporary storage for original byte */ DECLARE @newword binary(2) DECLARE @oldword binary(2) DECLARE @pubid int /* Publication identification number */ DECLARE @retcode int /* Return code for stored procedures */ -- DECLARE @zero binary(32) /* Constant: 0 */ DECLARE @artid int DECLARE @inactive tinyint DECLARE @objid int /* Article base table id */ DECLARE @tablename sysname select @inactive = 0 /* ** 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. ** Do not check if @ignore_distributor indicates brute force cleanup. */ IF ( (SELECT category & 1 FROM master..sysdatabases WHERE name = DB_NAME()) = 0 ) and ( @ignore_distributor = 0 ) BEGIN RAISERROR (14013, 16, -1) RETURN (1) END /* ** Parameter Check: @publication. ** Make sure that the publication exists and that it conforms to the ** rules for identifiers. */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @retcode <> 0 RETURN (1) SELECT @pubid = pubid FROM syspublications WHERE name = @publication IF @pubid IS NULL BEGIN RAISERROR (20026, 11, -1, @publication) RETURN (1) END ELSE /* ** Parameter Check: @article. ** Check to make sure that the article exists in the publication. */ IF @article IS NULL BEGIN RAISERROR (14043, 16, -1, '@article') RETURN (1) END /* EXECUTE @retcode = dbo.sp_validname @article IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) */ /* ** Make sure the article exists. */ SELECT @artid = artid FROM sysarticles WHERE pubid = @pubid AND name = @article IF @artid IS NULL BEGIN RAISERROR (20027, 11, -1, @article) RETURN (1) END /* ** Only unsubscribed articles may be modified. (excluding virtual subscriptions) */ IF EXISTS (SELECT * FROM syssubscriptions WHERE artid = @artid AND status <> @inactive AND srvid >= 0) BEGIN RAISERROR (14092, 11, -1) RETURN (1) END /* ** Error out if this is a not a table based article */ IF NOT EXISTS ( SELECT * FROM sysarticles WHERE artid = @artid AND pubid = @pubid AND (type & 1) = 1 ) BEGIN RAISERROR (14112, 11, -1 ) RETURN (1) END /* ** Parameter Check: @column. ** Check to make sure that the column exists and conforms to the rules ** for identifiers. */ /* IF @column IS NOT NULL BEGIN EXECUTE @retcode = dbo.sp_validname @column IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) END */ /* ** Parameter Check: @operation. ** The operation can be either 'add' or 'drop'. */ IF LOWER(@operation) NOT IN ('add', 'drop') BEGIN RAISERROR (14019, 16, -1) RETURN (1) END SELECT @objid = (SELECT objid FROM sysarticles WHERE artid = @artid) SELECT @tablename = OBJECT_NAME(@objid) if @column is not null begin -- If the publication is allow_sync_tran, we cannot drop the timestamp -- column from the partition. if exists (select * from syspublications where name = @publication and allow_sync_tran = 1) and LOWER(@operation) = 'drop' begin declare @ts_col sysname exec dbo.sp_MSis_col_replicated @publication, @article, 'timestamp', @ts_col OUTPUT if @ts_col = @column BEGIN if @@trancount > 0 begin ROLLBACK TRANSACTION articlecolumn commit tran end RAISERROR (21080, 16, -1) RETURN (1) END end end begin tran save TRANSACTION articlecolumn /* ** Make sure that the columns column is not NULL. */ IF EXISTS (SELECT * FROM sysarticles WHERE name = @article AND pubid = @pubid AND columns IS NULL) UPDATE sysarticles SET columns = 0x00 WHERE name = @article AND pubid = @pubid /* ** If no columns are specified, or if NULL is specified, set all ** the bits in the 'columns' column so all columns will be included. */ IF @column IS NULL BEGIN DECLARE hCartcolumn CURSOR LOCAL FAST_FORWARD FOR SELECT name FROM syscolumns where id = @objid END ELSE BEGIN DECLARE hCartcolumn CURSOR LOCAL FAST_FORWARD FOR SELECT @column END OPEN hCartcolumn FETCH hCartcolumn INTO @column WHILE (@@fetch_status <> -1) BEGIN DECLARE @columnid smallint /* Columnid-1 = bit to set */ /* ** Get the column id for this column. We'll use the column id ** to determine the bit in the 'columns' column. The bit we want ** is equal to the columnid - 1. */ SELECT @columnid = colid FROM syscolumns WHERE id = @objid AND name = @column IF ((@@error <> 0) OR (@columnid IS NULL)) BEGIN if @@trancount > 0 begin ROLLBACK TRANSACTION articlecolumn commit tran end RAISERROR (14020, 16, -1) RETURN (1) END /* ** Obtain the byte offset and the bit offset, then set the ** mask column for the bit we want to turn on. */ SELECT @word = CONVERT(tinyint, 16 - FLOOR((@columnid-1)/16)) SELECT @bit = (@columnid-1) % 16 IF LOWER(@operation) = 'add' SELECT @mval = POWER(2, @bit) ELSE SELECT @mval = ~POWER(2, @bit) select @mask = convert( binary(2), substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) ) /* ** Save the columns column in a temporary local variable so we ** can twiddle the bit and then put it back into the table. */ SELECT @columns = columns FROM sysarticles WHERE name = @article AND pubid = @pubid /* ** Fish out the byte we're interested in and save it in a ** a temporary local variable. If it's NULL, just set it ** to 0. Then apply the bitwise operator OR to twiddle the ** bit in the old byte and save it in another temporary ** local variable @newbyte. */ SELECT @oldword = CONVERT( binary(2), SUBSTRING( CONVERT( nvarchar,@columns), @word, 1) ) IF @oldword IS NULL SELECT @oldword = 0x0000 IF LOWER(@operation) = 'add' SELECT @newword = CONVERT(binary(2), convert(smallint, @oldword) | @mask) ELSE SELECT @newword = CONVERT(binary(2), convert(smallint, @oldword ) & @mask) SELECT @columns = CONVERT(binary(32), STUFF( convert(nchar(16),@columns), @word, 1, convert( nchar(1), @newword))) SELECT @idx = @idx + 1 IF LOWER(@operation) = 'drop' BEGIN /* Update Text\Image column status as not published */ EXECUTE @retcode = dbo.sp_MSarticletextcol @artid, @columnid, 'publish', @operation IF (@@error <> 0 OR @retcode <> 0) BEGIN if @@trancount > 0 begin ROLLBACK TRANSACTION articlecolumn commit tran end RAISERROR (14021, 16, -1) RETURN (1) END END /* ** Update the sysarticles table. Set the bit to 1 for the ** selected column. */ UPDATE sysarticles SET columns = @columns WHERE name = @article AND pubid = @pubid IF @@error <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRANSACTION articlecolumn commit tran end RAISERROR (14021, 16, -1) RETURN (1) END IF LOWER(@operation) = 'add' BEGIN /* Update Text\Image column status as not published */ EXECUTE @retcode = dbo.sp_MSarticletextcol @artid, @columnid, 'publish', @operation IF (@@error <> 0 OR @retcode <> 0) BEGIN if @@trancount > 0 begin ROLLBACK TRANSACTION articlecolumn commit tran end RAISERROR (14021, 16, -1) RETURN (1) END END FETCH hCartcolumn INTO @column END -- Synctran /* ** If publication is enabled for Synctran and sprocs are auto-generated - regenerate them */ declare @autogen_sync_procs_id bit declare @ins_proc_id int, @upd_proc_id int, @del_proc_id int declare @ins_proc sysname, @upd_proc sysname, @del_proc sysname, @owner sysname, @objname sysname declare @sync_pubid int declare @cmd nvarchar(4000) select @autogen_sync_procs_id = autogen_sync_procs, @sync_pubid = pubid from syspublications where name = @publication if @autogen_sync_procs_id = 1 and @refresh_synctran_procs = 1 begin -- Drop existing synctran procs select @owner = user_name(OBJECTPROPERTY(objid, 'OwnerId')) from sysarticles a, syspublications p where a.name = @article and p.name = @publication and a.pubid = p.pubid select @ins_proc_id = sync_ins_proc, @upd_proc_id = sync_upd_proc, @del_proc_id = sync_del_proc from sysarticleupdates where pubid = @pubid and artid = @artid if @ins_proc_id is not null begin select @objname = object_name(@ins_proc_id) exec @retcode = dbo.sp_MSdrop_object @object_name = @objname, @object_owner = @owner if @@error <> 0 or @retcode <> 0 return (1) end if @upd_proc_id is not null begin select @objname = object_name(@upd_proc_id) exec @retcode = dbo.sp_MSdrop_object @object_name = @objname, @object_owner = @owner if @@error <> 0 or @retcode <> 0 return (1) end if @del_proc_id is not null begin select @objname = object_name(@del_proc_id) exec @retcode = dbo.sp_MSdrop_object @object_name = @objname, @object_owner = @owner if @@error <> 0 or @retcode <> 0 return (1) end -- Now generate new ones select @ins_proc = 'sp_MSsync_ins_' + SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @sync_pubid)) select @upd_proc = 'sp_MSsync_upd_' + SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @sync_pubid)) select @del_proc = 'sp_MSsync_del_' + SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @sync_pubid)) -- check uniqueness of names and revert to ugly guid-based name if friendly name already exists if exists (select name from sysobjects where name in (@ins_proc, @upd_proc, @del_proc)) begin declare @guid_name nvarchar(36) select @guid_name = convert (nvarchar(36), newid()) -- remove '-' from guid name because rpc can't handle '-' select @guid_name = replace (@guid_name,'-','_') select @ins_proc = 'sp_MSsync_ins_' + @guid_name select @upd_proc = 'sp_MSsync_upd_' + @guid_name select @del_proc = 'sp_MSsync_del_' + @guid_name end if @ins_proc IS NULL begin if @@trancount > 0 ROLLBACK TRANSACTION RAISERROR (14043, 11, -1, '@ins_proc') RETURN (1) end if @upd_proc IS NULL begin if @@trancount > 0 ROLLBACK TRANSACTION RAISERROR (14043, 11, -1, '@upd_proc') RETURN (1) end if @del_proc IS NULL begin if @@trancount > 0 ROLLBACK TRANSACTION RAISERROR (14043, 11, -1, '@del_proc') RETURN (1) end exec @retcode = dbo.sp_MSgen_sync_tran_procs @publication, @article, @ins_proc, @upd_proc, @del_proc IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN articlecolumn commit tran end RETURN (1) END --retrieve sproc id's, fail if they don't exist SELECT @ins_proc_id = id FROM sysobjects WHERE name = @ins_proc SELECT @upd_proc_id = id FROM sysobjects WHERE name = @upd_proc SELECT @del_proc_id = id FROM sysobjects WHERE name = @del_proc IF (@ins_proc_id IS NULL) OR (@upd_proc_id IS NULL) OR (@del_proc_id IS NULL) BEGIN if @ins_proc_id IS NULL RAISERROR (20500, 16, 1, @ins_proc) if @upd_proc_id IS NULL RAISERROR (20500, 16, 1, @upd_proc) if @del_proc_id IS NULL RAISERROR (20500, 16, 1, @del_proc) if @@trancount > 0 begin ROLLBACK tran articlecolumn commit tran end RETURN (1) END -- perform update in sysarticleupdates update sysarticleupdates set sync_ins_proc = @ins_proc_id, sync_upd_proc = @upd_proc_id, sync_del_proc = @del_proc_id where pubid = @pubid and artid = @artid IF @@ERROR <> 0 BEGIN RAISERROR (20501, 16, -1) if @@trancount > 0 begin ROLLBACK tran articlecolumn commit tran end RETURN (1) END end -- end synctran /* ** Force the article cache to be refreshed with the new definition. ** Nothing to flush if brute force cleanup. */ if ( @ignore_distributor = 0 ) EXECUTE dbo.sp_replflush COMMIT TRANSACTION go grant execute on dbo.sp_articlecolumn to public go -------------------------------------------------------------------------------- --. sp_addarticle -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_addarticle') drop procedure sp_addarticle go raiserror('Creating procedure sp_addarticle', 0,1) go CREATE PROCEDURE sp_addarticle @publication sysname, /* publication name */ @article sysname, /* article name */ @source_table nvarchar (386) = NULL, /* table name */ @destination_table sysname = NULL, /* destination table name */ @vertical_partition nchar(5) = 'false', /* vertical partition */ @type sysname = NULL, /* article type */ @filter nvarchar (386) = NULL, /* stored procedure used to filter table */ @sync_object nvarchar (386) = NULL, /* view or table used for synchronization */ @ins_cmd nvarchar (255) = NULL, /* insert format string */ @del_cmd nvarchar (255) = NULL, /* delete format string */ @upd_cmd nvarchar (255) = NULL, /* update format string */ @creation_script nvarchar (127) = NULL, /* article schema script */ @description nvarchar (255) = NULL, /* article description */ @pre_creation_cmd nvarchar(10) = 'drop', /* 'none', 'drop', 'delete', 'truncate' */ @filter_clause ntext = NULL, /* where clause */ @schema_option binary(8) = NULL, @destination_owner sysname = NULL, @status tinyint = 16, /* Default: binary command format */ @source_owner sysname = NULL, /* NULL for 6.5 users, not NULL for 7.0 users */ @sync_object_owner sysname = NULL, /* NULL for 6.5 users, not NULL for 7.0 users */ @filter_owner sysname = NULL, /* NULL for 6.5 users, not NULL for 7.0 users */ @source_object sysname = NULL /* if @source_table is NULL, this parameter can not be NULL */ AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @bak_source sysname DECLARE @num_columns int DECLARE @accessid smallint DECLARE @db sysname DECLARE @filterid int DECLARE @object sysname DECLARE @owner sysname DECLARE @pubid int DECLARE @publish_bit smallint DECLARE @retcode int DECLARE @site sysname DECLARE @syncid int DECLARE @tabid int DECLARE @typeid smallint DECLARE @pkkey sysname DECLARE @i int DECLARE @indid int DECLARE @precmdid int DECLARE @object_type nchar(2) DECLARE @push tinyint DECLARE @dbname sysname DECLARE @cmd nvarchar(255) DECLARE @fHasPk int DECLARE @no_sync tinyint DECLARE @immediate_sync bit DECLARE @is_filter_in_use int DECLARE @distributor sysname DECLARE @distribdb sysname DECLARE @distproc nvarchar (255) DECLARE @article_id int DECLARE @sync_method tinyint -- SyncTran DECLARE @autogen_sync_procs_id int DECLARE @custom_proc_name varchar(32) DECLARE @guid varbinary(16) declare @allow_sync_tran bit DECLARE @repl_freq int SELECT @push = 0 SELECT @dbname = DB_NAME() SELECT @publish_bit = 1 SELECT @no_sync = 2 /* no sync type in syssubscriptions */ /* ** Security Check. */ exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Parameter Check: @article. ** The @article name cannot be NULL and must conform to the rules ** for identifiers. */ IF @article IS NULL BEGIN RAISERROR (14043, 16, -1, '@article') RETURN (1) END exec @retcode = dbo.sp_MSreplcheck_name @article if @@ERROR <> 0 or @retcode <> 0 return(1) if LOWER(@article) = 'all' BEGIN RAISERROR (14032, 16, -1, '@article') RETURN (1) END /* ** Parameter Check: @publication. ** The @publication name cannot be NULL and must conform to the rules ** for identifiers. */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @retcode <> 0 RETURN (1) /* ** Parameter Check: @destination_owner. ** The @destination_owner must conform to the rules ** for identifiers. */ if @destination_owner is not null BEGIN -- native bcp mode publications are for odbc subscribers. Destination -- owner name is not supported. if exists (select * from syspublications where name = @publication and sync_method = 1) begin raiserror(21039,16, -1) return(1) end EXECUTE @retcode = dbo.sp_validname @destination_owner IF @retcode <> 0 RETURN (1) END /* ** Parameter Check: @source_table. ** Check to see that the @source_table 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 @source_table IS NULL BEGIN if @source_object is NOT NULL select @source_table = @source_object else begin RAISERROR (14043, 16, -1, '@source_table') RETURN (1) end END IF @source_owner is NULL -- 6.5 users only begin IF @source_table LIKE '%.%.%' AND PARSENAME(@source_table, 3) <> DB_NAME() BEGIN RAISERROR (14004, 16, -1, @source_table) RETURN (1) END end -- For 7.0 users, @source_owner is not nullable. select @bak_source = @source_table IF @source_owner is not NULL begin select @source_table = QUOTENAME(@source_owner) + '.' + QUOTENAME(@source_table) IF @destination_table IS NULL SELECT @destination_table = @bak_source end ELSE IF @destination_table IS NULL -- Set destination_table if not provided or default by now. -- If @source_table is qualified (6.x behavior) only use table name for destination name. SELECT @destination_table = PARSENAME(@source_table, 1) select @num_columns=count(*) from syscolumns where id = object_id(@source_table) if @num_columns > 255 begin RAISERROR (20068, 16, @source_table, 255) RETURN (1) end /* ** Get the id of the @source_table */ SELECT @tabid = id, @object_type = type FROM sysobjects WHERE id = OBJECT_ID(@source_table) IF @tabid IS NULL BEGIN RAISERROR (14027, 11, -1, @source_table) RETURN (1) END -- at this point, we've done all the common parameter checks. -- If this is a procedure, branch to the proc execution publishing -- routine, otherwise continue processing as if it were a table IF @object_type = 'P' BEGIN begin tran save TRAN sp_addarticle EXECUTE @retcode = dbo.sp_MSaddexecarticle @publication, @article, @source_table, @destination_table, @type, @creation_script, @description, @pre_creation_cmd, @schema_option, @destination_owner, @article_id OUTPUT IF @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END ELSE GOTO DONE 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(@source_table)) AND type = 'U') BEGIN RAISERROR (14028, 16, -1) RETURN (1) END /* ** Parameter Check: @destination_table. ** If the destination table is not specified, assume it's the same ** as the source table. Make sure that the table name is not qualified. */ IF @destination_table LIKE '%.%.%' BEGIN RAISERROR (14001, 16, -1) RETURN (1) END IF @destination_table LIKE '%.%' BEGIN RAISERROR (14044, 16, -1, '@destination_table') RETURN (1) END /* ** Parameter Check: @vertical_partition ** Check to make sure that the vertical partition is either TRUE or FALSE. */ SELECT @vertical_partition = LOWER(@vertical_partition) IF @vertical_partition NOT IN ('true', 'false') BEGIN RAISERROR (14029, 16, -1) RETURN (1) END -- -- parameter check: @status -- IF (@status & ~24 ) <> 0 BEGIN RAISERROR( 21061, 16, -1, @status, @article ) RETURN (1) END /* ** Parameter Check: @filter ** Make sure that the filter is a valid stored procedure. */ IF @filter IS NOT NULL BEGIN IF @filter_owner IS NULL BEGIN select @object = PARSENAME( @filter, 1 ) select @owner = PARSENAME( @filter, 2 ) select @db = PARSENAME( @filter, 3 ) select @site = PARSENAME( @filter, 4 ) if @object IS NULL return 1 END ELSE BEGIN select @filter = QUOTENAME(@filter_owner) + '.' + QUOTENAME(@filter) END /* ** Get the id of the @filter */ select @filterid = id from sysobjects where id = OBJECT_ID(@filter) and type = 'RF' IF @filterid IS NULL BEGIN RAISERROR (14027, 11, -1, @filter) RETURN (1) END EXEC @is_filter_in_use = dbo.sp_MSdoesfilterhaveparent @filterid if( @is_filter_in_use <> 0 ) BEGIN RAISERROR( 21009, 11, -1 ) RETURN (1) END END ELSE select @filterid = 0 /* ** Get the pubid. */ -- SyncTran -- SELECT @pubid = pubid FROM syspublications WHERE name = @publication SELECT @pubid = pubid, @autogen_sync_procs_id = autogen_sync_procs, @sync_method = sync_method, @allow_sync_tran = allow_sync_tran FROM syspublications WHERE name = @publication -- end SyncTran 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 sysarticles WHERE pubid = @pubid AND name = @article) BEGIN RAISERROR (14030, 16, -1, @article, @publication) RETURN (1) END /* ** Set the typeid. The default type is logbased. Anything else is ** currently undefined (reserved for future use). ** ** @typeid type ** ======= ======== ** 1 logbased ** 3 logbased manualfilter ** 5 logbased manualview ** 7 logbased manualboth ** 8 proc exec (valid in dbo.sp_MSaddexecarticle) ** 24 serializable proc exec (valid in dbo.sp_MSaddexecarticle) */ IF @type IS NULL BEGIN SELECT @type = 'logbased' END ELSE IF LOWER(@type) NOT IN ('logbased', 'logbased manualfilter', 'logbased manualview', 'logbased manualboth') BEGIN RAISERROR (14023, 16, -1) RETURN (1) END IF LOWER(@type) = 'logbased' SELECT @typeid = 1 ELSE IF LOWER(@type) = 'logbased manualfilter' SELECT @typeid = 3 ELSE IF LOWER(@type) = 'logbased manualview' SELECT @typeid = 5 ELSE IF LOWER(@type) = 'logbased manualboth' SELECT @typeid = 7 /* ** 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 IF @sync_object IS NULL select @syncid = @tabid ELSE BEGIN IF @sync_object_owner is NULL -- 6.5 only BEGIN /* ** Parameter Check: @sync_object. ** Check to see that the sync_object is local and that it ** conforms to the rules for identifiers. */ select @object = PARSENAME( @sync_object, 1 ) select @owner = PARSENAME( @sync_object, 2 ) select @db = PARSENAME( @sync_object, 3 ) select @site = PARSENAME( @sync_object, 4 ) if @object IS NULL return 1 IF @sync_object LIKE '%.%.%' AND @db <> DB_NAME() BEGIN RAISERROR (14004, 16, -1, @sync_object) RETURN (1) END END -- end of 65 processing else -- for sphinx, @sync_object_owner can not be null select @sync_object = QUOTENAME(@sync_object_owner) + '.' + QUOTENAME(@sync_object) /* ** Get the id of the @sync_object */ SELECT @syncid = id FROM sysobjects WHERE id = OBJECT_ID(@sync_object) IF @syncid IS NULL BEGIN RAISERROR (14027, 11, -1, @sync_object) RETURN (1) END /* ** Make sure the sync object specified is a table or a view. */ IF NOT EXISTS (SELECT * FROM sysobjects WHERE id = (SELECT OBJECT_ID(@sync_object)) AND (type = 'U' or type = 'V')) BEGIN RAISERROR (14031, 16, -1) RETURN (1) END END /* ** If the publication is log-based, ** make sure there is a primary key on the source table. ** NOTE! sprok in SPSUP.SQL */ IF EXISTS (SELECT * FROM syspublications WHERE pubid = @pubid AND (repl_freq = 0 OR allow_sync_tran = 1) ) BEGIN EXEC @fHasPk = dbo.sp_MSreplsup_table_has_pk @tabid IF @fHasPk = 0 BEGIN RAISERROR (14088, 16, -1, @source_table) RETURN (1) END 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. */ SELECT @repl_freq = repl_freq from syspublications where name = @publication IF @schema_option IS NULL BEGIN -- Snapshot publication, no cust. proc. generation IF @repl_freq = 1 BEGIN SELECT @schema_option = 0x0000000000000071 END ELSE BEGIN SELECT @schema_option = 0x0000000000000073 END END /* ** Parameter Check: @schema_option ** If bit 0x2 is set, this cannot be an article for a snapshot publication ** */ IF ((CONVERT(INT, @schema_option) & 0x2) <> 0) AND (@repl_freq = 1) BEGIN RAISERROR (21143, 16, -1) RETURN (1) END -- If pub sync_type is character mode bcp(1) if @sync_method = 1 begin select @status = 0 if @ins_cmd is NULL select @ins_cmd = 'SQL' if @upd_cmd is NULL select @upd_cmd = 'SQL' if @del_cmd is NULL select @del_cmd = 'SQL' end /* ** Parameter Check: @schema_option ** If Autogeneration of custom procedures is not enabled ** then the default commands will be SQL */ IF ((CONVERT(int, @schema_option) & 0x2) = 0) BEGIN if @ins_cmd is NULL select @ins_cmd = 'SQL' if @upd_cmd is NULL select @upd_cmd = 'SQL' if @del_cmd is NULL select @del_cmd = 'SQL' END -- Autogenerate custom procedure names if not provided. -- If unable to construct a name because the article name is close to the maximum length, then create a -- name based on the database timestamp if ((@source_object is not NULL and len(@article) > 119) or (@source_object is NULL and len(@article) > 21)) or exists (select * from sysarticles where name = @article) begin set @guid = CONVERT(varbinary(16), LEFT(NEWID(),8)) exec @retcode = master.dbo.xp_varbintohexstr @guid, @custom_proc_name OUTPUT if @@error <> 0 or @retcode <> 0 RETURN(1) end else set @custom_proc_name = @article -- If no command then construct name if @ins_cmd is NULL begin if (@status & 16) <> 0 -- parameterized begin if @source_object is not NULL -- 7.0 format set @ins_cmd = N'CALL ' + convert (sysname, 'sp_MSins_' + @custom_proc_name) else -- 6.x compatible set @ins_cmd = N'CALL ' + convert(nvarchar(30), 'sp_MSins_' + @custom_proc_name) end else select @ins_cmd = 'SQL' end if @del_cmd is NULL begin if (@status & 16) <> 0 -- parameterized begin if @source_object is not NULL -- 7.0 format set @del_cmd = N'CALL ' + convert (sysname, 'sp_MSdel_' + @custom_proc_name) else -- 6.x compatible set @del_cmd = N'CALL ' + convert(nvarchar(30), 'sp_MSdel_' + @custom_proc_name) end else select @del_cmd = 'SQL' end if @upd_cmd is NULL begin if (@status & 16) <> 0 -- parameterized begin if @source_object is not NULL -- 7.0 format set @upd_cmd = N'MCALL ' + convert (sysname, 'sp_MSupd_' + @custom_proc_name) else -- 6.x compatible set @upd_cmd = N'CALL ' + convert(nvarchar(30), 'sp_MSupd_' + @custom_proc_name) end else select @upd_cmd = 'SQL' end -- SyncTran -- Add timestamp column if not exists if @allow_sync_tran = 1 and ObjectProperty(@tabid, 'TableHasTimestamp') = 0 begin exec ('alter table ' + @source_table + ' add msrepl_synctran_ts timestamp not null' ) IF @@ERROR <> 0 RETURN (1) end /* ** Add article to sysarticles and update sysobjects category bit. */ begin tran save TRAN sp_addarticle INSERT sysarticles (columns, creation_script, del_cmd, description, dest_table, filter, filter_clause, ins_cmd, name, objid, pre_creation_cmd, pubid, status, sync_objid, type, upd_cmd, schema_option, dest_owner) VALUES (0, @creation_script, @del_cmd, @description, @destination_table, @filterid, @filter_clause, @ins_cmd, @article, @tabid, @precmdid, @pubid, @status, @syncid, @typeid, @upd_cmd, @schema_option, @destination_owner) IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END SELECT @article_id = @@IDENTITY UPDATE sysobjects SET replinfo = replinfo | @publish_bit WHERE id = (SELECT objid FROM sysarticles WHERE name = @article and pubid = @pubid) IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END IF @filter IS NOT NULL BEGIN EXEC dbo.sp_MSsetfilterparent @filter, @tabid IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END END EXEC dbo.sp_MSsetfilteredstatus @tabid IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END /* ** Set all bits to '1' in the columns column to include all columns. */ IF @vertical_partition = 'false' BEGIN EXECUTE @retcode = dbo.sp_articlecolumn @publication, @article -- synctran , @refresh_synctran_procs = 0 IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END END /* ** 1. Set all bits to '1' for all columns in the primary key. ** 2. Set timestamp column bit to 1 if the publication is synctran */ ELSE BEGIN SELECT @indid = indid FROM sysindexes WHERE id = @tabid AND (status & 2048) <> 0 /* PK index */ /* ** First we'll figure out what the keys are. */ SELECT @i = 1 WHILE (@i <= 16) BEGIN SELECT @pkkey = INDEX_COL(@source_table, @indid, @i) if @pkkey is NULL break EXECUTE @retcode = dbo.sp_articlecolumn @publication, @article, @pkkey, 'add' -- synctran , @refresh_synctran_procs = 0 IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END select @i = @i + 1 END if @allow_sync_tran = 1 and ObjectProperty(@tabid, 'TableHasTimestamp') = 1 begin declare @ts_col sysname -- Get synctran column select @ts_col = name from syscolumns where id = @tabid and type_name(xtype) = 'timestamp' if @ts_col is not null begin EXECUTE @retcode = dbo.sp_articlecolumn @publication, @article, @ts_col, 'add' -- synctran , @refresh_synctran_procs = 0 IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END end end END ------------------------------------------------------------------------------ -- if table based article does not use a view for sync, create one and use it ------------------------------------------------------------------------------ if @tabid = @syncid begin -- generate view name declare @viewname varchar(255) set @guid = CONVERT(varbinary(16), LEFT(NEWID(),8)) exec @retcode = master.dbo.xp_varbintohexstr @guid, @viewname OUTPUT if @@ERROR <> 0 OR @retcode <> 0 begin if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end return 1 end set @viewname = 'syncobj_' + @viewname -- create view for object synchronization exec @retcode = dbo.sp_articleview @publication, @article, @viewname, @filter_clause if @@ERROR <> 0 OR @retcode <> 0 begin if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end return 1 end end DONE: /* ** 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 RAISERROR (14071, 16, -1) RETURN (1) 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, @article_id = @article_id, @destination_object = @destination_table, @source_owner = @source_owner, @source_object = @bak_source, @description = @description IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END /* If the publication is immediate_sync type ** 1. Change the immediate_sync_ready status to false ** 2. Add a virtual subscription on the article ** 3. Add subscriptions for all the subscriber ** that have no_sync subscriptions on the publication ** ** Note: Subscriptions for subscribers that have automatic sync subscriptions ** on the publication will be added by snasphot agent. */ if EXISTS (SELECT * FROM syspublications WHERE name = @publication AND immediate_sync = 1 ) BEGIN UPDATE syspublications SET immediate_sync_ready = 0 WHERE name = @publication IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END EXECUTE @retcode = dbo.sp_addsubscription @publication = @publication, @article = @article, @subscriber = NULL, @destination_db = 'virtual', @sync_type = 'automatic', @status = NULL, @reserved = 'internal' IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END -- Note: We have to add the subscriptions to the new article before -- the virtual subscriptions being activated!!!! Otherwise, the snapshot -- transactions may be skipped by dist agents. EXECUTE @retcode = dbo.sp_refreshsubscriptions @publication IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END END /* ** if @autogen_sync_procs_id is 1, autogen the sync tran procs, including name */ if @tabid > 0 and @autogen_sync_procs_id = 1 begin declare @insproc sysname, @updproc sysname, @delproc sysname select @insproc = 'sp_MSsync_ins_' + SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @pubid)) select @updproc = 'sp_MSsync_upd_' + SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @pubid)) select @delproc = 'sp_MSsync_del_' + SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @pubid)) -- check uniqueness of names and revert to ugly guid-based name if friendly name already exists if exists (select name from sysobjects where name in (@insproc, @updproc, @delproc)) begin declare @guid_name nvarchar(36) select @guid_name = convert (nvarchar(36), newid()) -- remove '-' from guid name because rpc can't handle '-' select @guid_name = replace (@guid_name,'-','_') select @insproc = 'sp_MSsync_ins_' + @guid_name select @updproc = 'sp_MSsync_upd_' + @guid_name select @delproc = 'sp_MSsync_del_' + @guid_name end if @insproc IS NULL begin if @@trancount > 0 begin ROLLBACK TRANSACTION sp_addarticle commit tran end RAISERROR (14043, 11, -1, '@insproc') RETURN (1) end if @updproc IS NULL begin if @@trancount > 0 begin ROLLBACK TRANSACTION sp_addarticle commit tran end RAISERROR (14043, 11, -1, '@updproc') RETURN (1) end if @delproc IS NULL begin if @@trancount > 0 begin ROLLBACK TRANSACTION sp_addarticle commit tran end RAISERROR (14043, 11, -1, '@delproc') RETURN (1) end exec @retcode = dbo.sp_articlesynctranprocs @publication, @article, @insproc, @updproc, @delproc, true IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRANSACTION sp_addarticle commit tran end RETURN (1) END end -- end SyncTran COMMIT TRANSACTION go grant execute on dbo.sp_addarticle to public go -------------------------------------------------------------------------------- --. sp_MSpublishdb -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSpublishdb') drop procedure sp_MSpublishdb go raiserror('Creating procedure sp_MSpublishdb', 0,1) go CREATE PROCEDURE sp_MSpublishdb( @value sysname, @ignore_distributor bit = 0 ) AS SET NOCOUNT ON /* ** Declarations. */ declare @quoted_db sysname declare @db_name sysname declare @command nvarchar(255) declare @description nvarchar(500) declare @category_name nvarchar(100) DECLARE @agentname nvarchar(300) DECLARE @dbname sysname DECLARE @retcode int DECLARE @distributor sysname DECLARE @distribdb sysname DECLARE @distproc nvarchar (255) DECLARE @replicate_bit smallint SELECT @replicate_bit = 2 /* ** Initialization */ SELECT @dbname = 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 /* ** Drop and then create central publish tables */ /* ** Drop first if exists */ EXEC @retcode = dbo.sp_MSdrop_pub_tables IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END /* ** Create central publish tables */ EXEC @retcode = dbo.sp_MScreate_pub_tables IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END END ELSE /* Disable the database for publishing. */ BEGIN /* ** Remove all subscriptions in the database. ** WARNING : must owner qualify proc calls for these to run inside server on restore/attach */ EXEC @retcode = dbo.sp_dropsubscription @publication = 'all', @article = 'all', @subscriber = 'all', @ignore_distributor = @ignore_distributor IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END -- Used for attach and restored db. -- sysservers table in master db might be changed so that -- sp_dropsubscription won't work. Delete the table directly. -- Before dropping the table, we need to unmark repl bits in sysobjects -- see below delete syssubscriptions where srvid >= 0 IF @@ERROR <> 0 BEGIN return (1) END /* ** Remove all publications and articles in the database. */ EXEC @retcode = dbo.sp_droppublication @publication = 'all', @ignore_distributor = @ignore_distributor IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END /* ** Remove all published database transactions from the distribution ** database. */ if @ignore_distributor = 0 begin SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSremove_published_jobs ' EXEC @retcode = @distproc @@SERVERNAME, @dbname IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END end /* ** Publishing shutdown, remove all xacts pending distribution */ /* ensure we can get in as logreader */ EXEC @retcode = dbo.sp_replflush IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END /* unmark all xacts marked for replication */ select @quoted_db = QUOTENAME(@dbname) EXEC ( 'USE ' + @quoted_db + ' exec dbo.sp_repldone NULL, NULL, 0, 0, 1' ) IF @@ERROR <> 0 BEGIN return (1) END /* release our hold on the db as logreader */ EXEC dbo.sp_replflush IF @@ERROR <> 0 BEGIN RETURN(1) END /* ** Drop central publish tables */ EXEC @retcode = dbo.sp_MSdrop_pub_tables IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END -- Used for attached and restored db. -- sysservers table in master db might be changed so that -- sp_dropsubscription won't work. Unmark repl bits in sysobjects -- directly. UPDATE sysobjects SET replinfo = replinfo & ~@replicate_bit END return (0) GO -------------------------------------------------------------------------------- --. sp_MSget_synctran_commands -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSget_synctran_commands') drop procedure sp_MSget_synctran_commands go raiserror('Creating procedure sp_MSget_synctran_commands', 0,1) go CREATE PROCEDURE sp_MSget_synctran_commands( @publication sysname /* publication name */, @article sysname = 'all', @command_only bit = 0 /* 0 if called by snapshot agent, 1 if called by sp_script_..., */ ) AS SET NOCOUNT ON DECLARE @artid int DECLARE @tabid int DECLARE @retcode int declare @art_type tinyint declare @filter_id int declare @filter_clause nvarchar(4000) declare @columns binary(32) DECLARE @pubid int, @art_name sysname, @posted_synctran_artid int, @dest_table sysname, @dest_owner sysname, @proc_owner sysname /* ** Initializations. */ select @posted_synctran_artid = 0 /* ** Security Check. ** We use login_name stored in syssubscriptions to manage security ** Do a relaxed security check here. */ exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Parameter Check: @publication ** Check to make sure that the publication exists, that it's not NULL, ** and that it conforms to the rules for identifiers. */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) SELECT @pubid = pubid FROM syspublications WHERE name = @publication IF @pubid IS NULL BEGIN RAISERROR (20026, 11, -1, @publication) RETURN (1) END -- If the publication does not allow sync tran return nothing IF NOT EXISTS (SELECT * FROM syspublications WHERE pubid = @pubid and allow_sync_tran = 1) RETURN(0) CREATE TABLE #art_commands (artid int NOT NULL, commands nvarchar(4000) NULL, id int identity NOT NULL) declare @all_article bit if lower(@article) = 'all' select @all_article = 1 else select @all_article = 0 DECLARE hCsynctran_arts CURSOR LOCAL FAST_FORWARD FOR SELECT art.artid, art.objid, art.dest_table, art.dest_owner, art.name, art.type, art.filter, art.columns FROM sysarticles art, syspublications pub WHERE pub.pubid = @pubid and pub.pubid = art.pubid and (art.type & 0x1) = 1 and (art.name = @article or @all_article = 1) FOR READ ONLY OPEN hCsynctran_arts FETCH hCsynctran_arts INTO @artid, @tabid, @dest_table, @dest_owner, @art_name, @art_type, @filter_id, @columns WHILE (@@fetch_status <> -1) BEGIN /* ** Determine conflict detection method */ declare @ts_col sysname -- Determine if table has timestamp property select @ts_col = NULL if ObjectProperty(@tabid, 'TableHasTimestamp') = 1 begin exec dbo.sp_MSis_col_replicated @publication, @art_name, 'timestamp', @ts_col OUTPUT end declare @replcmd nvarchar(4000) declare @insproc sysname, @updproc sysname, @delproc sysname declare @identity_col sysname declare @identity_prop tinyint select @posted_synctran_artid = @artid select @insproc = null, @updproc = null, @delproc = null -- Get sproc names and owner name of the sprocs -- Note artid is unique select @insproc = o.name, @proc_owner = u.name from sysobjects o, sysarticleupdates a, sysusers u where a.artid = @artid and a.sync_ins_proc = o.id and u.uid = o.uid select @updproc = o.name from sysobjects o, sysarticleupdates a where a.artid = @artid and a.sync_upd_proc = o.id select @delproc = o.name from sysobjects o, sysarticleupdates a where a.artid = @artid and a.sync_del_proc = o.id if @insproc IS NULL begin CLOSE hCsynctran_arts DEALLOCATE hCsynctran_arts RAISERROR (14043, 11, -1, '@insproc') RETURN (1) end if @updproc IS NULL begin CLOSE hCsynctran_arts DEALLOCATE hCsynctran_arts RAISERROR (14043, 11, -1, '@updproc') RETURN (1) end if @delproc IS NULL begin CLOSE hCsynctran_arts DEALLOCATE hCsynctran_arts RAISERROR (14043, 11, -1, '@delproc') RETURN (1) end -- Determine if published table has identity col select @identity_col = NULL if ObjectProperty(@tabid, 'TableHasIdentity') = 1 exec @retcode = dbo.sp_MSis_col_replicated @publication, @art_name, 'identity', @identity_col OUTPUT -- Horizontal partition select @filter_clause = 'null' if @filter_id <> 0 begin -- We don't handle manual filters; allow all updates if ((@art_type & 0x3) = 0x3) select @filter_clause = '' else select @filter_clause = RTRIM(LTRIM(CONVERT(nvarchar(4000), filter_clause))) from sysarticles where artid = @artid end declare @fullname nvarchar(512) declare @indkey int declare @indid int declare @key sysname declare @col sysname declare @this_col int declare @src_cols int declare @primary_key_bitmap varbinary(4000) declare @byte varbinary(1) declare @i_byte int declare @num_bytes int declare @i_bit tinyint declare @bitmap_str varchar(8000) declare @bitmap varbinary(4000) -- Get qualified name exec dbo.sp_MSget_qualified_name @tabid, @fullname output -- Get number of columns in the partition. exec dbo.sp_MSget_col_position @tabid, @columns, @key, @col output, @this_col output, 1, -- Get num of columns in the partition. @src_cols output select @num_bytes = @src_cols / 8 + 1 -- Set varbinary length set @byte = 0 set @primary_key_bitmap = @byte set @i_byte = 1 while @i_byte < @num_bytes begin set @primary_key_bitmap = @primary_key_bitmap + @byte set @i_byte = @i_byte + 1 end -- get index id exec @indid = dbo.sp_MStable_has_unique_index @tabid set @indkey = 1 while @indkey < 16 and index_col(@fullname, @indid, @indkey) is not null begin set @key = index_col(@fullname, @indid, @indkey) exec dbo.sp_MSget_col_position @tabid, @columns, @key, @col output, @this_col output set @i_byte = 1 + (@this_col-1) / 8 set @i_bit = power(2, (@this_col-1) % 8 ) set @byte = substring(@primary_key_bitmap, @i_byte, 1 ) set @byte = @byte | @i_bit if @i_byte = 1 begin set @bitmap = @byte end else begin set @bitmap = substring(@primary_key_bitmap, 1, @i_byte - 1) set @bitmap = @bitmap + @byte end if @i_byte <> @num_bytes begin set @primary_key_bitmap = @bitmap + substring(@primary_key_bitmap, @i_byte + 1, @num_bytes - @i_byte) end else set @primary_key_bitmap = @bitmap select @indkey = @indkey + 1 end exec @retcode = master..xp_varbintohexstr @primary_key_bitmap, @bitmap_str output if @retcode <> 0 or @@error <> 0 return 1 if @dest_owner is null begin select @dest_owner = N'null' end select @replcmd = '{call sp_addsynctriggers (N' + quotename(@dest_table,'''') + ', N' + quotename(@dest_owner,'''') + ', N' + quotename(@@SERVERNAME,'''') + ', N' + quotename(db_name(),'''') + ', N' + quotename(@publication,'''') + ', N' + quotename(@insproc,'''') + ', N' + quotename(@updproc,'''') + ', N' + quotename(@delproc,'''') + ', N' + quotename(@proc_owner,'''') + ', N' + ISNULL(quotename(@identity_col,''''),'''null''') + ', N' + ISNULL(quotename(@ts_col,''''), '''null''') + ', N''' + replace(@filter_clause,'''', '''''') + ''', ' + @bitmap_str + ')}' insert into #art_commands values (@artid, @replcmd) FETCH hCsynctran_arts INTO @artid, @tabid, @dest_table, @dest_owner, @art_name, @art_type, @filter_id, @columns end -- end SyncTran if @command_only = 0 select * from #art_commands order by id else select commands from #art_commands order by id CLOSE hCsynctran_arts DEALLOCATE hCsynctran_arts go grant exec on dbo.sp_MSget_synctran_commands to public go -------------------------------------------------------------------------------- --. sp_MSis_pk_col -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSis_pk_col') drop procedure sp_MSis_pk_col go raiserror('Creating procedure sp_MSis_pk_col', 0,1) go create proc sp_MSis_pk_col @source_table sysname, @colname sysname, @indid int as begin declare @indkey int select @indkey = 1 while @indkey < 16 and index_col(@source_table, @indid, @indkey) is not null begin if index_col(@source_table, @indid, @indkey) = @colname return (1) select @indkey = @indkey + 1 end return (0) end GO -------------------------------------------------------------------------------- --. sp_MSdrop_expired_subscription -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSdrop_expired_subscription') drop procedure sp_MSdrop_expired_subscription go raiserror('Creating procedure sp_MSdrop_expired_subscription', 0,1) go create procedure sp_MSdrop_expired_subscription 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 @independent_agent bit declare @article sysname declare @publication sysname declare @pubid int declare @artid int declare @publisher sysname declare @subscriber sysname declare @subscriber_id smallint declare @subscriber_db sysname declare @publisher_db sysname declare @out_of_date int 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 @open_cursor nvarchar(400) /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) /* ** 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 RAISERROR (20036, 16, -1) return (1) END SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MShelp_subscription_status ' select @publisher = @@SERVERNAME select @publisher_db = db_name() declare PC CURSOR LOCAL FAST_FORWARD for select DISTINCT name, pubid, independent_agent, retention from syspublications p open PC fetch PC into @publication, @pubid, @independent_agent, @retention WHILE (@@fetch_status <> -1) BEGIN -- Don't do anything if the retention is zero, this means -- subscriptions to the publication will never expire IF @retention = 0 BEGIN GOTO ZERO_RETENTION END declare SC CURSOR LOCAL FAST_FORWARD for select s.srvid, s.dest_db, a.name from syssubscriptions s, sysarticles a where a.pubid= @pubid and s.artid = a.artid and s.srvid<>-1 for read only open SC fetch SC into @subscriber_id, @subscriber_db, @article WHILE (@@fetch_status <> -1) BEGIN select @subscriber=srvname from master..sysservers where srvid=@subscriber_id exec @retcode = @distproc @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @subscriber = @subscriber, @subscriber_db = @subscriber_db, @retention = @retention, @out_of_date = @out_of_date OUTPUT, @independent_agent = @independent_agent if @retcode<>0 or @@ERROR<>0 begin close SC deallocate SC close PC deallocate PC return (1) end IF (@out_of_date = 1) begin exec @retcode = dbo.sp_dropsubscription -- publisher_db.dbo.sp_dropsubscription @publication = @publication, @article = @article, @subscriber = @subscriber, @destination_db = @subscriber_db if @retcode <>0 or @@ERROR<>0 begin close SC deallocate SC close PC deallocate PC return (1) end raiserror(14157, 10, -1, @subscriber, @publication) end fetch SC into @subscriber_id, @subscriber_db, @article END CLOSE SC DEALLOCATE SC ZERO_RETENTION: fetch PC into @publication, @pubid, @independent_agent, @retention END CLOSE PC DEALLOCATE PC GO -------------------------------------------------------------------------------- --. sp_MSscript_update_statement -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSscript_update_statement') drop procedure sp_MSscript_update_statement go raiserror('Creating procedure sp_MSscript_update_statement', 0,1) go create procedure sp_MSscript_update_statement @publication sysname, @article sysname, @objid int, @columns binary(32) as declare @cmd nvarchar(4000) declare @cmd2 nvarchar(4000) declare @qualname nvarchar(512) declare @colname sysname declare @typestring nvarchar(4000) declare @spacer nvarchar(1) declare @ccoltype sysname declare @src_cols int declare @this_col int declare @rc int declare @column nvarchar(4000) declare @num_col int declare @art_col int -- position in the article partition. declare @isset int select @src_cols = count(*) from syscolumns where id = @objid exec sp_MSget_qualified_name @objid, @qualname OUTPUT select @cmd2 = N'update ' + @qualname + N' set' -- col names select @spacer = N' ' select @this_col = 1 select @cmd = N'' -- If the table have only identity in pk and a ts col, update statement will be empty -- and the query will fail. Prevent it here. select @num_col = 0 select @art_col = 0 -- script update while @this_col <= @src_cols begin -- Get the ordinal of the article partition or not. exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns if @isset != 0 select @art_col = @art_col + 1 exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output if @rc = 0 and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1) begin if rtrim(@ccoltype) not like N'timestamp' and ColumnProperty(@objid, @colname, 'IsIdentity') != 1 begin if @cmd2 is not null begin exec dbo.sp_MSflush_command @cmd2 output, 1 select @cmd2 = null end select @num_col = @num_col + 1 -- Optimization: -- Get null or actual column name -- Note: the output is quoted. exec dbo.sp_MSget_synctran_column @ts_col = null, @op_type = null , -- 'ins, 'upd', 'del' @is_new = null, @primary_key_bitmap = null, @colname = @colname, @this_col = @this_col, @column = @column output, @from_proc = 1, @art_col = @art_col -- position in the partition. select @cmd = @cmd + @spacer + QUOTENAME(@colname) + N' = ' + @column select @spacer = N',' -- flush command if necessary exec dbo.sp_MSflush_command @cmd output, 0 end end select @this_col = @this_col + 1 end -- save off cmd fragment if @num_col > 0 begin exec dbo.sp_MSflush_command @cmd output, 1 -- Determine method of conflict detection and add where clause if ObjectProperty(@objid, 'TableHasTimestamp') = 1 begin exec @rc = dbo.sp_MSis_col_replicated @publication, @article, 'timestamp', @colname OUTPUT if @rc = 1 begin insert into #proctext(procedure_text) values( N' ') exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd ts', @colname, 4 end end else begin insert into #proctext(procedure_text) values( N' ') exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd rc', null, 4 end end else -- set the @@rowcount insert into #proctext(procedure_text) values( N' select @retcode = @retcode ') go grant execute on dbo.sp_MSscript_update_statement to public go -------------------------------------------------------------------------------- --. sp_MSscript_sync_ins_proc -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSscript_sync_ins_proc') drop procedure sp_MSscript_sync_ins_proc go raiserror('Creating procedure sp_MSscript_sync_ins_proc', 0,1) go create procedure sp_MSscript_sync_ins_proc @publication sysname, @article sysname, @procname sysname as declare @source_objid int declare @colname sysname declare @indid int declare @cmd nvarchar(4000) declare @ins_cmd nvarchar(4000) declare @columns binary(32) declare @outvars nvarchar(4000) declare @rc int set nocount on -- Create temp table create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL) -- preamble common to all synctran procs exec @rc = dbo.sp_MSscript_beginproc @publication, @article, @procname, @source_objid output, @columns output if @rc = 0 return -- construct parameter list exec dbo.sp_MSscript_params @source_objid, @columns, null, 1, @outvars output -- construct body of procedure insert into #proctext(procedure_text) values( N' as ') -- set cycle detection insert into #proctext(procedure_text) values(N'declare @retcode int ') insert into #proctext(procedure_text) values( N'exec @retcode = dbo.sp_replsetoriginator @orig_server, @orig_db ') insert into #proctext(procedure_text) values( N'if @retcode <> 0 or @@error <> 0 return -1 ') -- script out security check exec dbo.sp_MSscript_security @publication -- script out subscription validation exec dbo.sp_MSscript_validate_subscription @publication, @article -- Work around for case where article has 1 col that is not user-modfied (identity, timestamp) exec @rc = dbo.sp_MStable_not_modifiable @source_objid, @columns if @rc = 1 insert into #proctext(procedure_text) values( N'exec sp_MSreplraiserror 20516 ') else begin exec @indid = dbo.sp_MStable_has_unique_index @source_objid if @outvars <> null and @indid = 0 -- no insert/update allowed if timestamp/identity col and no unique index insert into #proctext(procedure_text) values( N'exec sp_MSreplraiserror 20516 ') else begin -- script insert statemnt exec dbo.sp_MSscript_insert_statement @source_objid, @columns -- script closing exec dbo.sp_MSscript_endproc @source_objid, 'ins', @columns, @outvars end end -- send fragments to client select procedure_text from #proctext order by c1 asc go grant execute on dbo.sp_MSscript_sync_ins_proc to public go -------------------------------------------------------------------------------- --. sp_MSscript_sync_upd_proc -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSscript_sync_upd_proc') drop procedure sp_MSscript_sync_upd_proc go raiserror('Creating procedure sp_MSscript_sync_upd_proc', 0,1) go create procedure sp_MSscript_sync_upd_proc @publication sysname, @article sysname, @procname sysname as declare @source_objid int declare @colname sysname declare @indid int declare @cmd nvarchar(4000) declare @ins_cmd nvarchar(4000) declare @columns binary(32) declare @outvars nvarchar(4000) declare @rc int set nocount on -- Create temp table create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL) -- preamble common to all synctran procs exec @rc = dbo.sp_MSscript_beginproc @publication, @article, @procname, @source_objid output, @columns output if @rc = 0 return -- construct parameter list exec dbo.sp_MSscript_params @source_objid, @columns, null, 1, @outvars output insert into #proctext(procedure_text) values( N', ') exec dbo.sp_MSscript_params @source_objid, @columns, N'_old', 0, null -- Script bitmap parameter insert into #proctext(procedure_text) values( N', @bitmap varbinary(4000)') -- construct body of procedure insert into #proctext(procedure_text) values( N' as ') -- set cycle detection insert into #proctext(procedure_text) values(N'declare @retcode int ') insert into #proctext(procedure_text) values( N'exec @retcode = dbo.sp_replsetoriginator @orig_server, @orig_db ') insert into #proctext(procedure_text) values( N'if @retcode <> 0 or @@error <> 0 return -1 ') -- script out security check exec dbo.sp_MSscript_security @publication -- script out subscription validation exec dbo.sp_MSscript_validate_subscription @publication, @article -- Work around for case where article has 1 col that is not user-modfied (identity, timestamp) exec @rc = dbo.sp_MStable_not_modifiable @source_objid, @columns if @rc = 1 insert into #proctext(procedure_text) values( N'exec sp_MSreplraiserror 20516 ') else begin exec @indid = dbo.sp_MStable_has_unique_index @source_objid if @outvars <> null and @indid = 0 -- no insert/update allowed if timestamp/identity col and no unique index insert into #proctext(procedure_text) values( N'exec sp_MSreplraiserror 20516 ') else begin -- script update statemnt exec dbo.sp_MSscript_update_statement @publication, @article, @source_objid, @columns -- script closing exec dbo.sp_MSscript_endproc @source_objid, 'upd', @columns, @outvars end end -- send fragments to client select procedure_text from #proctext order by c1 asc go grant execute on dbo.sp_MSscript_sync_upd_proc to public go -------------------------------------------------------------------------------- --. sp_MSscript_sync_del_proc -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSscript_sync_del_proc') drop procedure sp_MSscript_sync_del_proc go raiserror('Creating procedure sp_MSscript_sync_del_proc', 0,1) go create procedure sp_MSscript_sync_del_proc @publication sysname, @article sysname, @procname sysname as declare @source_objid int declare @colname sysname declare @indid int declare @cmd nvarchar(4000) declare @ins_cmd nvarchar(4000) declare @columns binary(32) declare @outvars nvarchar(4000) declare @rc int set nocount on -- Create temp table create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL) -- preamble common to all synctran procs exec @rc = dbo.sp_MSscript_beginproc @publication, @article, @procname, @source_objid output, @columns output if @rc = 0 return -- construct parameter list exec dbo.sp_MSscript_params @source_objid, @columns, N'_old', 0, null -- construct body of procedure insert into #proctext(procedure_text) values( N' as ') -- set cycle detection insert into #proctext(procedure_text) values(N'declare @retcode int ') insert into #proctext(procedure_text) values( N'exec @retcode = dbo.sp_replsetoriginator @orig_server, @orig_db ') insert into #proctext(procedure_text) values( N'if @retcode <> 0 or @@error <> 0 return -1 ') -- script out security check exec dbo.sp_MSscript_security @publication -- script out subscription validation exec dbo.sp_MSscript_validate_subscription @publication, @article -- Work around for case where article has 1 col that is not user-modfied (identity, timestamp) exec @rc = dbo.sp_MStable_not_modifiable @source_objid, @columns if @rc = 1 insert into #proctext(procedure_text) values( N'exec sp_MSreplraiserror 20516 ') else begin exec @indid = dbo.sp_MStable_has_unique_index @source_objid if @indid = 0 -- no delete allowed if no unique index insert into #proctext(procedure_text) values( N'exec sp_MSreplraiserror 20516 ') else begin -- script insert statemnt exec dbo.sp_MSscript_delete_statement @publication, @article, @source_objid, @columns -- script closing exec dbo.sp_MSscript_endproc @source_objid, 'del', @columns, null end end -- send fragments to client select procedure_text from #proctext order by c1 asc go grant execute on dbo.sp_MSscript_sync_del_proc to public go -------------------------------------------------------------------------------- --. sp_scriptinsproc -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_scriptinsproc') drop procedure sp_scriptinsproc go raiserror('Creating procedure sp_scriptinsproc', 0,1) go create procedure sp_scriptinsproc @artid int as declare @cmd nvarchar(4000) declare @dest_owner nvarchar(255) declare @dest_tabname sysname declare @src_objid int declare @columns binary(32) declare @ins_cmd nvarchar(255) declare @dest_proc sysname declare @src_cols int declare @this_col int declare @art_col int declare @isset int declare @typestring nvarchar(255) declare @spacer nvarchar(1) if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 ) begin raiserror (14155, 16, 1 ) return 1 end -------- create temp table for command fragments create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL) -------- get sysarticles information select @dest_owner = dest_owner, @dest_tabname = dest_table, @src_objid = objid, @columns = columns, @ins_cmd = ins_cmd from sysarticles where artid = @artid if @dest_owner is not null begin select @dest_owner = QUOTENAME( @dest_owner ) + N'.' end else begin select @dest_owner = N'' end -------- get dest proc name if( 1 != charindex( N'CALL', upper(@ins_cmd) ) ) or @ins_cmd is null begin raiserror (14156, 16, 1 ) return 1 end select @dest_proc = substring( @ins_cmd, 6, len( @ins_cmd ) - 4 ) select @cmd = N'create procedure ' + QUOTENAME(@dest_proc) -------- construct parameter list select @this_col = 1 select @art_col = 1 select @src_cols = max(colid) from syscolumns where id = @src_objid select @spacer = N' ' while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1) begin if len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' end exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) + N' ' + @typestring select @art_col = @art_col + 1 select @spacer = N',' end select @this_col = @this_col + 1 end -- save off cmd fragment insert into #proctext(procedure_text) values( @cmd ) insert into #proctext(procedure_text) values( N'as' ) ------- construct proc body select @cmd = N'insert into ' + @dest_owner + QUOTENAME(@dest_tabname) + N' values (' select @this_col = 1 select @art_col = 1 select @spacer = N' ' while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid) begin if len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' end select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) select @art_col = @art_col + 1 select @spacer = N',' end select @this_col = @this_col + 1 end -- finish up proc body select @cmd = @cmd + N' )' -- save off cmd fragement insert into #proctext(procedure_text) values( @cmd ) -- send fragements to client select procedure_text from #proctext order by c1 asc go grant exec on dbo.sp_scriptinsproc to public go -------------------------------------------------------------------------------- --. sp_scriptdelproc -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_scriptdelproc') drop procedure sp_scriptdelproc go raiserror('Creating procedure sp_scriptdelproc', 0,1) go create procedure sp_scriptdelproc @artid int as declare @cmd nvarchar(4000) declare @dest_owner nvarchar(255) declare @dest_tabname sysname declare @src_objid int declare @pkcolumns binary(32) declare @del_cmd nvarchar(255) declare @dest_proc sysname declare @src_cols int declare @this_col int declare @art_col int declare @isset int declare @typestring nvarchar(255) declare @spacer nvarchar(10) if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 ) begin raiserror (14155, 16, 1 ) return 1 end -------- create temp table for command fragments create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL) -- get sysarticles information select @dest_owner = dest_owner, @dest_tabname = dest_table, @src_objid = objid, @del_cmd = del_cmd from sysarticles where artid = @artid if @dest_owner is not null begin select @dest_owner = QUOTENAME( @dest_owner ) + N'.' end else begin select @dest_owner = N'' end -------- get dest proc name if( 1 != charindex( N'CALL', upper(@del_cmd) ) ) or @del_cmd is null begin raiserror (14156, 16, 1 ) return 1 end select @dest_proc = substring( @del_cmd, 6, len( @del_cmd ) - 4 ) select @cmd = N'create procedure ' + QUOTENAME(@dest_proc) -------- construct parameter list select @this_col = 1 select @art_col = 1 select @src_cols = max(colid) from syscolumns where id = @src_objid select @spacer = N' ' exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1) begin if len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' end exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT select @cmd = @cmd + @spacer + N'@pkc' + convert( nvarchar, @art_col ) + N' ' + @typestring select @art_col = @art_col + 1 select @spacer = N',' end select @this_col = @this_col + 1 end -- save off insert into #proctext(procedure_text) values( @cmd ) insert into #proctext(procedure_text) values( N'as' ) ------- construct proc body insert into #proctext(procedure_text) values( N'delete ' + @dest_owner + QUOTENAME(@dest_tabname) ) exec dbo.sp_scriptpkwhereclause @src_objid, @src_cols, @pkcolumns -- flush to client select procedure_text from #proctext order by c1 asc go grant exec on dbo.sp_scriptdelproc to public go -------------------------------------------------------------------------------- --. sp_scriptupdproc -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_scriptupdproc') drop procedure sp_scriptupdproc go raiserror('Creating procedure sp_scriptupdproc', 0,1) go create procedure sp_scriptupdproc @artid int as declare @cmd nvarchar(4000) declare @dest_owner nvarchar(255) declare @dest_tabname sysname declare @src_objid int declare @artcolumns binary(32) declare @pkcolumns binary(32) declare @upd_cmd nvarchar(255) declare @dest_proc sysname declare @src_cols int declare @this_col int declare @art_col int declare @pkart_col int declare @isset int declare @typestring nvarchar(255) declare @spacer nvarchar(10) if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 ) begin raiserror (14155, 16, 1 ) return 1 end -------- create temp table for command fragments create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL) -------- get sysarticles information select @dest_owner = dest_owner, @dest_tabname = dest_table, @src_objid = objid, @artcolumns = columns, @upd_cmd = upd_cmd from sysarticles where artid = @artid if @dest_owner is not null begin select @dest_owner = QUOTENAME( @dest_owner ) + N'.' end else begin select @dest_owner = N'' end -------- get dest proc name if( 1 != charindex( N'CALL', upper(@upd_cmd) ) ) or @upd_cmd is null begin raiserror (14156, 16, 1 ) return 1 end select @dest_proc = substring( @upd_cmd, 6, len( @upd_cmd ) - 4 ) insert into #proctext( procedure_text ) values ( N'create procedure ' + QUOTENAME(@dest_proc) + N' ') -------- construct parameter list select @src_cols = max(colid) from syscolumns where id = @src_objid exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output exec dbo.sp_scriptupdateparams @src_objid, @src_cols, @artcolumns, @pkcolumns insert into #proctext(procedure_text) values ( N'as' ) -------- now create the update statement -- construct test to see if pk has changed -- only do this if the article has columns not included in the pk if @artcolumns != @pkcolumns begin select @cmd = N'if' select @this_col = 1 select @art_col = 1 select @pkart_col = 1 select @spacer = ' ' while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1) begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns if @isset != 0 begin select @cmd = @cmd + @spacer + N'@c'+convert( nvarchar, @art_col ) + N' = @pkc' + convert( nvarchar, @pkart_col ) select @spacer = N' and ' select @pkart_col = @pkart_col + 1 if len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' end end select @art_col = @art_col + 1 end select @this_col = @this_col + 1 end insert into #proctext(procedure_text) values( @cmd ) -- construct update if pk hasn't changed select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set' -- create SET clause select @this_col = 1 select @art_col = 1 select @spacer = N' ' while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1) begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns if @isset = 0 begin select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = @c' + convert( nvarchar, @art_col ) select @spacer = N',' if len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' end end select @art_col = @art_col + 1 end select @this_col = @this_col + 1 end insert into #proctext(procedure_text) values( @cmd ) exec dbo.sp_scriptpkwhereclause @src_objid, @src_cols, @pkcolumns insert into #proctext(procedure_text) values( N'else' ) end -- end if artcols != pkcols -- construct update if pk has changed select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set' -- create SET clause select @this_col = 1 select @art_col = 1 select @spacer = N' ' while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1) begin select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = @c' + convert( nvarchar, @art_col ) select @art_col = @art_col + 1 select @spacer = N',' if len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' end end select @this_col = @this_col + 1 end insert into #proctext(procedure_text) values( @cmd ) exec dbo.sp_scriptpkwhereclause @src_objid, @src_cols, @pkcolumns -- flush to client select procedure_text from #proctext order by c1 asc go grant exec on dbo.sp_scriptupdproc to public go -------------------------------------------------------------------------------- --. sp_scriptmappedupdproc -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_scriptmappedupdproc') drop procedure sp_scriptmappedupdproc go raiserror('Creating procedure sp_scriptmappedupdproc', 0,1) go create procedure sp_scriptmappedupdproc @artid int as declare @cmd nvarchar(4000) declare @dest_owner nvarchar(255) declare @dest_tabname sysname declare @src_objid int declare @artcolumns binary(32) declare @pkcolumns binary(32) declare @upd_cmd nvarchar(255) declare @dest_proc sysname declare @src_cols int declare @art_cols int declare @this_col int declare @art_col int declare @pkart_col int declare @isset int declare @bytestr nvarchar(10) declare @bitstr nvarchar(10) declare @typestring nvarchar(255) declare @spacer nvarchar(10) declare @exists_else bit select @exists_else = 0 if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 ) begin raiserror (14155, 16, 1 ) return 1 end -------- create temp table for command fragments create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) ) -------- get sysarticles information select @dest_owner = dest_owner, @dest_tabname = dest_table, @src_objid = objid, @artcolumns = columns, @upd_cmd = upd_cmd from sysarticles where artid = @artid if @dest_owner is not null begin select @dest_owner = QUOTENAME( @dest_owner ) + N'.' end else begin select @dest_owner = N'' end -------- get dest proc name if( 1 != charindex( N'MCALL', upper(@upd_cmd) ) ) or @upd_cmd is null begin raiserror (14156, 16, 1 ) return 1 end select @dest_proc = substring( @upd_cmd, 7, len( @upd_cmd ) - 5 ) insert into #proctext( procedure_text ) values ( N'create procedure ' + QUOTENAME(@dest_proc) + N' ' ) -------- construct parameter list select @src_cols = max(colid) from syscolumns where id = @src_objid exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output exec dbo.sp_scriptupdateparams @src_objid, @src_cols, @artcolumns, @pkcolumns ----- add changed data bitmap select @this_col = 1 select @art_col = 1 while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid) begin select @art_col = @art_col + 1 end select @this_col = @this_col + 1 end -- Note that bitmap size is based on number of article columns -- (computed by loop above) not source table columns select @cmd = N',@bitmap binary(' + convert(nvarchar,1+(@art_col-1) / 8) + N')' insert into #proctext(procedure_text) values( @cmd ) insert into #proctext(procedure_text) values( N'as' ) -- construct IF statement -- do this only if the article contains columns not included in the pk if @artcolumns != @pkcolumns begin select @this_col = 1 select @art_col = 1 select @spacer = N' ' select @cmd = N'if' while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1) begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns if @isset != 0 begin select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 ) select @bitstr = convert( nvarchar, power(2, (@art_col-1) % 8 ) ) select @cmd = @cmd + @spacer + N'substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr + N' = ' + @bitstr select @spacer = N' or ' if len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' end end select @art_col = @art_col + 1 end select @this_col = @this_col + 1 end insert into #proctext(procedure_text) values( @cmd ) end -- if artcolumns != pkcolumns -- construct update statement including PK columns insert into #proctext(procedure_text) values( N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set' ) -- create SET clause consisting of CASE statements select @this_col = 1 select @art_col = 1 select @spacer = N'' while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid) begin select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 ) select @bitstr = convert( nvarchar, power(2, (@art_col-1) % 8 ) ) insert into #proctext(procedure_text) values ( @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = case substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr + N' when ' + @bitstr + N' then ' + N'@c'+ convert( nvarchar, @art_col ) + N' else ' + QUOTENAME(col_name( @src_objid, @this_col)) + N' end' ) select @spacer = ',' select @art_col = @art_col + 1 end select @this_col = @this_col + 1 end -- create where clause exec dbo.sp_scriptpkwhereclause @src_objid, @src_cols, @pkcolumns -- construct UPDATE that does not set PK cols -- only do this if the article contains columns that are not included -- in the pk if @artcolumns != @pkcolumns begin -- create SET clause consisting of CASE statements select @this_col = 1 select @art_col = 1 select @spacer = N'' while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid) begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns if @isset = 0 begin if (@exists_else = 0) begin insert into #proctext(procedure_text) values( N'else' ) insert into #proctext(procedure_text) values( N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set' ) select @exists_else = 1 end select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 ) select @bitstr = convert( nvarchar, power(2, (@art_col-1) % 8 ) ) insert into #proctext(procedure_text) values ( @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = case substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr + N' when ' + @bitstr + N' then ' + N'@c'+ convert( nvarchar, @art_col ) + N' else ' + QUOTENAME(col_name( @src_objid, @this_col)) + N' end' ) select @spacer = ',' end select @art_col = @art_col + 1 end select @this_col = @this_col + 1 end if @exists_else=1 exec dbo.sp_scriptpkwhereclause @src_objid, @src_cols, @pkcolumns end select procedure_text from #proctext order by c1 asc go grant exec on dbo.sp_scriptmappedupdproc to public go -------------------------------------------------------------------------------- --. Merge repl objects (rladmin.sql) -------------------------------------------------------------------------------- dump tran master with no_log go -------------------------------------------------------------------------------- --. sp_MSdrop_rladmin -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSdrop_rladmin') drop procedure sp_MSdrop_rladmin go 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 if exists (select * from sysobjects where type = 'P' and name = 'sp_MSmakeexpandproc') drop procedure sp_MSmakeexpandproc 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 if exists (select * from sysobjects where type = 'P' and name = 'sp_MSget_subtypedatasrc') drop procedure sp_MSget_subtypedatasrc if exists (select * from sysobjects where type = 'P' and name = 'sp_mergecleanupmetadata') drop procedure sp_mergecleanupmetadata if exists (select * from sysobjects where type = 'P' and name = 'sp_MScleanup_metadata') drop procedure sp_MScleanup_metadata go -------------------------------------------------------------------------------- --. sp_addmergearticle -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_addmergearticle') drop procedure sp_addmergearticle 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 IF @schema_option = 0x0000000000000000 BEGIN RAISERROR (3217, 16, -1, '@schema_option') RETURN (1) 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 xp_regread failed, is it because distributor server is running on Shiloh */ IF @retcode <> 0 or @resolver_clsid IS NULL begin EXECUTE @retcode = @distproc 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\Microsoft SQL Server\75\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 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 grant execute on dbo.sp_addmergearticle to public go -------------------------------------------------------------------------------- --. sp_changemergearticle -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_changemergearticle') drop procedure sp_changemergearticle 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 IF exists (select * from #tab_changearticle where value = 0x0000000000000000) BEGIN RAISERROR (3217, 16, -1, 'schema_option') 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 grant execute on dbo.sp_changemergearticle to public go -------------------------------------------------------------------------------- --. sp_addmergepublication -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_addmergepublication') drop procedure sp_addmergepublication 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? */ @keep_partition_changes nvarchar(5) = 'false' /* Optimized Partition Updates/Deletes */ ) 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 declare @keep_before_values_int 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 /* ** Parameter Check: @keep_partition_changes. */ if LOWER(@keep_partition_changes) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@keep_partition_changes') RETURN (1) END if LOWER(@keep_partition_changes) = 'true' set @keep_before_values_int = 1 else set @keep_before_values_int = 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, keep_before_values) 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, @keep_before_values_int) if @@ERROR <> 0 begin goto FAILURE end /* Add row to represent reciprocal subscription */ /* Note that we have overloaded last_updated column of this table for publication */ insert sysmergesubscriptions(subid, partnerid, datasource_type, srvid, db_name, status, priority, pubid, subscriber_type, subscription_type, sync_type, login_name, last_validated) values (@pubid, @pubid, 0, @srvid, @db_name, @statid, @priority, @pubid, @global, @push, @automatic, suser_sname(suser_sid()), getdate()) 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 grant execute on dbo.sp_addmergepublication to public go -------------------------------------------------------------------------------- --. sp_helpmergepublication -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_helpmergepublication') drop procedure sp_helpmergepublication 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, keep_partition_changes int NULL, snapshot_status int 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, keep_partition_changes, snapshot_status) 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, pubs.keep_before_values, case when (pubs.retention=0) or (pubs.snapshot_ready=0) or (dateadd(day, pubs.retention, subs.last_validated)>getdate()) then pubs.snapshot_ready else 3 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 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, keep_partition_changes, has_subscription, snapshot_status) 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, pubs.keep_before_values, 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, case when (pubs.retention=0) or (pubs.snapshot_ready=0) or dateadd(day, pubs.retention, subs.last_validated)>getdate() then pubs.snapshot_ready else 3 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 grant execute on dbo.sp_helpmergepublication to public go -------------------------------------------------------------------------------- --. sp_reinitmergesubscription -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_reinitmergesubscription') drop procedure sp_reinitmergesubscription 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 declare @subname sysname declare @subdb sysname declare @pubname sysname declare @subsrvid 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, pubs.name, subs.srvid, subs.db_name 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, @pubname, @subsrvid, @subdb while (@@fetch_status<>-1) BEGIN -- Security check if not exists (select * from sysmergesubscriptions subs1 where (suser_sname(suser_sid()) = subs1.login_name OR is_member('db_owner')=1 OR is_srvrolemember('sysadmin') = 1) and subid = @subid) continue select @subname=srvname from master..sysservers where srvid=@subsrvid 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, @pubname, @subname, @subdb, 1 if @@ERROR<>0 BEGIN goto Failure END fetch next from SYN_CUR into @subid, @subscription_type, @publisher, @publisher_db, @pubname, @subsrvid, @subdb 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 grant execute on dbo.sp_reinitmergesubscription to public go -------------------------------------------------------------------------------- --. sp_MSpublicationview -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSpublicationview') drop procedure sp_MSpublicationview 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 @join_before_view sysname declare @before_name sysname declare @before_viewname sysname declare @unqual_sourcename sysname declare @article sysname declare @art_nick int declare @join_nick int declare @join_filterclause nvarchar(4000) declare @bool_filterclause nvarchar(4000) declare @view_rule nvarchar(4000) declare @before_view_rule nvarchar(4000) declare @before_objid int 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), @before_viewname = OBJECT_NAME(before_view_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 if @before_viewname IS NOT NULL begin exec ('drop view ' + @before_viewname) 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, @before_objid = before_image_objid from sysmergearticles where nickname=@art_nick and pubid = @pubid set @before_name = OBJECT_NAME(@before_objid) if @before_name is not null begin exec @retcode = dbo.sp_MSguidtostr @pubid, @guidstr out set @before_viewname = @before_name + '_v_' + @guidstr end else set @before_viewname = NULL 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 @unqual_sourcename = QUOTENAME(OBJECT_NAME(@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), @join_before_view = object_name(before_image_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 if @before_name is not null begin set @before_view_rule = 'select * from ' + @before_name + ' ' + @unqual_sourcename + ' where exists (select * from ' + @join_viewname + ' ' + @unqual_jointable + ' where ' + @join_filterclause + ') or exists (select * from ' + @join_before_view + ' ' + @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), @join_before_view = object_name(before_image_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 if @before_name is not null set @before_view_rule = @before_view_rule + ' or exists (select * from ' + @join_viewname + ' ' + @unqual_jointable + ' where ' + @join_filterclause + ') or exists (select * from ' + @join_before_view + ' ' + @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 begin set @view_rule = @view_rule + ' union select ' + @source_object + '.rowguidcol from '+ @source_object + ' where '+ @bool_filterclause if @before_name is not null set @before_view_rule = @before_view_rule + ' or ' + @bool_filterclause end -- 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 */ begin select @view_rule = ' select * from '+ @source_object + ' where '+ @bool_filterclause if @before_name is not null set @before_view_rule = ' select * from ' + @before_name + ' ' + @unqual_sourcename + ' where ' + @bool_filterclause end 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, @source_objid end update sysmergearticles set sync_objid = OBJECT_ID (@viewname), view_type = @permanent, view_sel_proc = @procname where artid = @artid and pubid = @pubid if @before_name is not null begin exec @retcode = sp_MScreatebeforetable @source_objid if @retcode <> 0 or @@ERROR <> 0 return (1) exec ('create view ' + @before_viewname + ' as ' + @before_view_rule) execute sp_MS_marksystemobject @before_viewname update sysmergearticles set before_view_objid = OBJECT_ID (@before_viewname) where artid = @artid and pubid = @pubid end 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, @source_objid 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 grant execute on dbo.sp_MSpublicationview to public go -------------------------------------------------------------------------------- --. sp_addmergesubscription -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_addmergesubscription') drop procedure sp_addmergesubscription 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 declare @datasrctype int declare @datasrcpath sysname /* ** Initializations. */ set @datasource_type = 0 /* Default SQL Server */ set @datasource_path = NULL set @datasrctype = 0 /* Default SQL Server */ set @datasrcpath = 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 ELSE BEGIN exec @retcode = dbo.sp_MSget_subtypedatasrc @subscriber, @distributor, @distribdb, @datasrctype OUTPUT, @datasrcpath OUTPUT if @retcode<>0 return (1) if (@datasrctype = 4) or (@datasrctype = 5) BEGIN select @datasource_type = @datasrctype select @datasource_path = @datasrcpath END 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 = password 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 = @distributor_password, @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 grant execute on dbo.sp_addmergesubscription to public go -------------------------------------------------------------------------------- --. sp_dropmergesubscription -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_dropmergesubscription') drop procedure sp_dropmergesubscription 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 @retcode = dbo.sp_dropmergesubscription @publication = @publication, @subscriber = @subscriber, @subscriber_db = @subscriber_db, @subscription_type = 'push', @ignore_distributor = @ignore_distributor, @reserved = 1 if @retcode<>0 or @@ERROR<>0 return (1) EXECUTE @retcode = dbo.sp_dropmergesubscription @publication = @publication, @subscriber = @subscriber, @subscriber_db = @subscriber_db, @subscription_type = 'pull', @ignore_distributor = @ignore_distributor, @reserved = 1 if @retcode<>0 or @@ERROR<>0 return (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 grant execute on dbo.sp_dropmergesubscription to public go -------------------------------------------------------------------------------- --. sp_changemergefilter -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_changemergefilter') drop procedure sp_changemergefilter 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') INSERT INTO #temp VALUES ('join_unique_key') select * FROM #tab1 RETURN (0) END if @value is null begin raiserror (14028, 16, -1) return (1) end IF LOWER(@property)='join_unique_key' BEGIN IF LOWER(@value) NOT IN ('true','false') BEGIN RAISERROR(14137,16,-1) RETURN(1) END if LOWER(@value) = 'true' update sysmergesubsetfilters set join_unique_key=1 where join_filterid=@join_filterid else update sysmergesubsetfilters set join_unique_key=0 where join_filterid=@join_filterid if @@ERROR <> 0 or @retcode<>0 goto FAILURE 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 grant execute on dbo.sp_changemergefilter to public go -------------------------------------------------------------------------------- --. sp_MSmakeexpandproc -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSmakeexpandproc') drop procedure sp_MSmakeexpandproc 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 @before_viewname 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 @joinguidname 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, @before_viewname = object_name(before_view_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 @joinguidname = name from syscolumns where id = @join_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 skippedexpand = 1 and rowguid in (select rowguid from #belong where flag = 0) 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 update #notbelong set flag = ' + @filterid_str + ' where flag < ' + @filterid_str + ' /* 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 @before_viewname is not null set @cmd_piece = @cmd_piece + ' insert into #notbelong (tablenick, rowguid, flag) select ' + @base_nickstr + ', ' + @base_table + '.rowguidcol, -1 from ' + @base_owner + '.' + @base_table + ', ' + @before_viewname + ' ' + @join_table + ', #notbelong nb where (' + @join_clause + ') and ' + @join_table + '.' + @joinguidname + ' = 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 -------------------------------------------------------------------------------- --. sp_deletemergeconflictrow -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_deletemergeconflictrow') drop procedure sp_deletemergeconflictrow go 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 rowguidcol = ''' 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 -------------------------------------------------------------------------------- --. sp_MSget_subtypedatasrc -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSget_subtypedatasrc') drop procedure sp_MSget_subtypedatasrc go raiserror('Creating procedure sp_MSget_subtypedatasrc', 0,1) go CREATE PROCEDURE sp_MSget_subtypedatasrc @subscriber sysname, @distributor sysname, @distribdb sysname, @datasrctype int OUTPUT, @datasrc sysname OUTPUT AS SET NOCOUNT ON DECLARE @provider_name sysname DECLARE @jet_subscriber tinyint DECLARE @oledb_subscriber tinyint DECLARE @oracle_subscriber tinyint DECLARE @distproc nvarchar(255) DECLARE @cmd nvarchar(512) set @jet_subscriber = 2 set @oledb_subscriber = 3 set @oracle_subscriber = 5 create table #subtype ( type tinyint not null, ) SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_executesql' SELECT @cmd = 'select type from MSsubscriber_info where UPPER(subscriber) = ''' + UPPER(@subscriber) + ''' and UPPER(publisher) = ''' + @@servername + '''' insert into #subtype exec @distproc @cmd if (@@error <> 0 or @@rowcount <> 1) begin drop table #subtype raiserror(14085, 16, -1) return 1 end select @datasrctype = type from #subtype create table #server_info ( providername nvarchar(256) null, datasource nvarchar(3750) null, -- this is nvarchar(4000) in sysservers, but we want to -- avoid sev 10 info msg on create table with > 8060 bytes ) SELECT @cmd = 'select providername, datasource from master..sysservers where UPPER(srvname) = ''' + UPPER(@subscriber) + '''' insert into #server_info exec @distproc @cmd if (@@error <> 0 or @@rowcount <> 1) begin drop table #subtype drop table #server_info raiserror(14085, 16, -1) return 1 end select @datasrc = datasource, @provider_name = providername from #server_info /* ** Jet and Oracle subscribers are actually added to MSsubscriber_info as OLE DB subscribers, ** since they can be used in transactional replication also. ** Map the type to Jet or Oracle based on OLE DB provider name. */ if (@datasrctype = @oledb_subscriber) BEGIN if (upper(@provider_name) = 'MICROSOFT.JET.OLEDB.4.0') select @datasrctype = @jet_subscriber else if (upper(@provider_name) = 'MSDAORA') select @datasrctype = @oracle_subscriber END drop table #subtype drop table #server_info return 0 GO grant exec on dbo.sp_MSget_subtypedatasrc to public go -------------------------------------------------------------------------------- --. Merge repl objects (rlcore.sql) -------------------------------------------------------------------------------- dump tran master with no_log go -------------------------------------------------------------------------------- --. sp_MSaddguidindex -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSaddguidindex') drop procedure sp_MSaddguidindex 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)) begin select @colname = QUOTENAME(@colname) exec ('create unique index ' + @indexname + ' on ' + @qualified_name + ' (' + @colname + ')') if @@ERROR <>0 return (1) end return (0) go grant exec on dbo.sp_MSaddguidindex to public go ------------------------------------------------------------------------------- --. sp_MStablenamefromnick -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MStablenamefromnick') drop procedure sp_MStablenamefromnick 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(21124, 16, -1, @nick) return (1) end return (0) go -------------------------------------------------------------------------------- --. sp_MSmakegeneration -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSmakegeneration') drop procedure sp_MSmakegeneration 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 set @dt2 = DATEADD(day, -2, @dt) select @gen = max(generation) from MSmerge_genhistory if exists (select * from MSmerge_genhistory where guidlocal = @guidnull and generation < @gen - 100 and coldate < @dt2 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 coldate < @dt2 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 coldate < @dt2 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 coldate < @dt2 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 coldate < @dt2 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 holdlock) where nickname = @art_nick and gen_cur is not null if @gen is null begin 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 -- 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 grant exec on dbo.sp_MSmakegeneration to public go ------------------------------------------------------------------------------- --. sp_MSaddupdatetrigger -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSaddupdatetrigger') drop procedure sp_MSaddupdatetrigger 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 @command3 nvarchar(4000) declare @inscommand nvarchar(2000) 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 + '%' /* Don't let them update the rowguid column */ if columnproperty( @objid, @colname , 'isrowguidcol')=1 set @ifcol = 'if update(' + QUOTENAME(@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 -- Initialize string for inserting to before_image table exec sp_MSgetbeforetableinsert @objid, @inscommand output /* 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 + ' FROM inserted as I JOIN ' + @viewname + ' as V ON (I.rowguidcol=V.rowguid) where tablenick = @tablenick if @@error <> 0 GOTO FAILURE ' + @inscommand set @command3 = ' 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 + ' FROM inserted as I JOIN ' + @viewname + ' as V ON (I.rowguidcol=V.rowguid) where tablenick = @tablenick if @@error <> 0 GOTO FAILURE ' + @inscommand + ' end else begin set @partgen = NULL set @joingen = NULL update ' + @viewname + ' set lineage = { fn UPDATELINEAGE(lineage, @nick) }, generation = @newgen, ' + @cvstr2 + ' FROM inserted as I JOIN ' + @viewname + ' as V ON (I.rowguidcol=V.rowguid) where tablenick = @tablenick 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 + @command3) if @@ERROR <> 0 begin raiserror(20064, 16, -1) return (1) end execute ('sp_MS_marksystemobject ''' + @trigname + '''') GO -------------------------------------------------------------------------------- --. sp_MSaddmergetriggers -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSaddmergetriggers') drop procedure sp_MSaddmergetriggers 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 @command2 nvarchar(4000) declare @inscommand nvarchar(2000) 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) -- set up the before image table if one is desired exec dbo.sp_MScreatebeforetable @objid -- Initialize string for inserting to before_image table exec sp_MSgetbeforetableinsert @objid, @inscommand output 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 @command2 = ' set @lineage = { fn UPDATELINEAGE(0x0, @nickname) } insert into ' + @tsview + ' (rowguid, tablenick, type, lineage, generation, reason) select rowguidcol, @tablenick, 1, { fn UPDATELINEAGE(COALESCE(c.lineage, @lineage), @nickname) }, @newgen, @reason from deleted d left outer join ' + @viewname + ' c on 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 + @inscommand + @command2) 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 grant exec on dbo.sp_MSaddmergetriggers to public go -------------------------------------------------------------------------------- --. Merge repl objects (rlrecon.sql) -------------------------------------------------------------------------------- dump tran master with no_log go -------------------------------------------------------------------------------- --. sp_MSdrop_rlrecon -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSdrop_rlrecon') drop procedure sp_MSdrop_rlrecon go 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 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_MSexclause') drop procedure sp_MSexclause if exists (select * from sysobjects where type = 'P' and name = 'sp_MSmakectsview') drop procedure sp_MSmakectsview 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_MSinitdynamicsubscriber') drop procedure sp_MSinitdynamicsubscriber 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_MSgetmetadatabatch') drop procedure sp_MSgetmetadatabatch 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 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 if exists (select * from sysobjects where type = 'P' and name = 'sp_MScreatebeforetable') drop procedure sp_MScreatebeforetable if exists (select * from sysobjects where type = 'P' and name = 'sp_MShelpcreatebeforetable') drop procedure sp_MShelpcreatebeforetable if exists (select * from sysobjects where type = 'P' and name = 'sp_MShelpalterbeforetable') drop procedure sp_MShelpalterbeforetable if exists (select * from sysobjects where type = 'P' and name = 'sp_MSgetbeforetableinsert') drop procedure sp_MSgetbeforetableinsert if exists (select * from sysobjects where type = 'P' and name = 'sp_MSfixlineagemismatch') drop procedure sp_MSfixlineagemismatch if exists (select * from sysobjects where type = 'P' and name = 'sp_MSinsertgenerationschemachanges') drop procedure sp_MSinsertgenerationschemachanges go -------------------------------------------------------------------------------- --. sp_changemergepublication -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P ' and name = 'sp_changemergepublication') drop procedure sp_changemergepublication 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 declare @schemaversion int declare @schemaguid uniqueidentifier declare @schematype int declare @schematext nvarchar(2000) declare @artid uniqueidentifier /* ** 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 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 = 9 /* change retention */ select @schematext = 'exec dbo.sp_MSchange_retention '+ '''' + convert(nchar(36),@pubid) + '''' + ',' + '''' + @value + '''' exec @retcode=sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext if @@ERROR<>0 or @retcode<>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 -------------------------------------------------------------------------------- --. sp_MSchange_retention -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSchange_retention') drop procedure sp_MSchange_retention GO raiserror('Creating procedure sp_MSchange_retention', 0,1) GO -- @value has to be unicode too. CREATE PROCEDURE sp_MSchange_retention (@pubid uniqueidentifier, @value nvarchar(255)) as update sysmergepublications set retention = convert(int, @value) where pubid = @pubid go grant execute on dbo.sp_MSchange_retention to public GO -------------------------------------------------------------------------------- --. sp_MScleanup_metadata -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P ' and name = 'sp_MScleanup_metadata') drop procedure sp_MScleanup_metadata GO raiserror('Creating procedure sp_MScleanup_metadata', 0,1) GO create procedure sp_MScleanup_metadata @pubid uniqueidentifier AS declare @retcode int /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) delete from MSmerge_contents where tablenick in (select nickname from sysmergearticles where pubid=@pubid) delete from MSmerge_tombstone where tablenick in (select nickname from sysmergearticles where pubid=@pubid) GO grant execute on dbo.sp_MScleanup_metadata to public go -------------------------------------------------------------------------------- --. sp_MSsetconflictscript -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSsetconflictscript') drop procedure sp_MSsetconflictscript go raiserror('Creating procedure sp_MSsetconflictscript', 0,1) GO 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 grant exec on dbo.sp_MSsetconflictscript to public go -------------------------------------------------------------------------------- --. sp_MSenumschemachange -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSenumschemachange') drop procedure sp_MSenumschemachange go raiserror('Creating procedure sp_MSenumschemachange', 0,1) GO CREATE PROCEDURE sp_MSenumschemachange( @pubid uniqueidentifier, @schemaversion int, @compatibility_level int = 7000000 -- for 70 RTM and 70 SP1; SP2 and up will pass in a bigger value ) 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 /* ** For 70 RTM and SP1, we want to filter out type 9 (retention propagation) and 16 (metadata cleanup) ** and 5 ( last rec generation ) and 6 (last sent generation) ** which they do not support. SP2 subscriber will be passing in 7000200, which gets all schema types ** SP2 publishers have to offer */ select pubid, artid, schemaversion, schemaguid, schematype, schematext from sysmergeschemachange where schemaversion > @schemaversion and pubid = @pubid and (@compatibility_level>7000000 or (schematype not in (5, 6, 9, 16))) order by schemaversion return (0) go grant exec on dbo.sp_MSenumschemachange to public go -------------------------------------------------------------------------------- --. sp_MShelpmergearticles -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MShelpmergearticles') drop procedure sp_MShelpmergearticles 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 create table #helpmergearticles ( art_name sysname NOT NULL, table_name sysname NOT NULL, table_owner sysname NOT NULL, artid uniqueidentifier NOT NULL, pre_creation_command tinyint NULL, pubid uniqueidentifier NOT NULL, nickname int NOT NULL, column_tracking int NOT NULL, status tinyint NULL, resolver_clsid nvarchar(50) NULL, conflict_script nvarchar(255) NULL, conflict_table nvarchar(258) NULL, insert_proc sysname NULL, update_proc sysname NULL, select_proc sysname NULL, destination_object sysname NULL, missing_col_count int NULL, missing_cols varbinary(128) NULL, rowguid_colname sysname NOT NULL, article_resolver nvarchar(255) NULL, resolver_info nvarchar(255) NULL, subset_filterclause nvarchar(1000) NULL, has_join int NULL ) INSERT INTO #helpmergearticles (art_name, table_name, table_owner, artid, pre_creation_command, pubid, nickname, column_tracking, status, resolver_clsid, conflict_script, conflict_table, insert_proc, update_proc, select_proc, destination_object, missing_col_count, missing_cols, rowguid_colname, article_resolver, resolver_info, subset_filterclause)( 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 ) update #helpmergearticles set has_join = 1 where nickname in (select join_nickname from sysmergesubsetfilters) select * from #helpmergearticles order by nickname return (0) go grant exec on dbo.sp_MShelpmergearticles to public go -------------------------------------------------------------------------------- --. sp_MSmakesystableviews -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSmakesystableviews') drop procedure sp_MSmakesystableviews go raiserror('Creating procedure sp_MSmakesystableviews', 0,1) GO 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 declare @dbname sysname declare @command nvarchar(500) /* ** 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 */ set @command = 'sp_MSmakectsview ' + QUOTENAME(@publication) + ' , ' + @contentsview set @dbname = db_name() exec @retcode = master..xp_execresultset @command, @dbname if @@ERROR<>0 OR @retcode <>0 return (1) /* ** generate the view for MSmerge_tombstone. In SP2, the change was made to make the view ** return 0 rows since it is unnecessary and expensive to propagate the tombstones. ** In order to leave all the other moving parts unchanged, we decided to let the view ** return 0 rows. */ exec ('create view ' + @tombstoneview + ' as select * from MSmerge_tombstone where 1 = 2 and 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 grant exec on dbo.sp_MSmakesystableviews to public go -------------------------------------------------------------------------------- --. sp_MSmakectsview -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSmakectsview') drop procedure sp_MSmakectsview go raiserror('Creating procedure sp_MSmakectsview', 0,1) GO create procedure sp_MSmakectsview @publication sysname, @ctsview sysname AS declare @pubid uniqueidentifier declare @pubidstr nvarchar(40) declare @objid int declare @tablenick int declare @tablenickstr nvarchar(12) declare @command_piece nvarchar(2000) declare @rowguidcolname sysname declare @view_type int declare @view_name sysname declare @union_after_first nvarchar(100) set @union_after_first = '' select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name() set @pubidstr = '''' + convert(nchar(36), @pubid) + '''' /* Check for the no filtering cases */ if not exists (select * from sysmergesubsetfilters where pubid = @pubid) and not exists (select * from sysmergearticles where pubid = @pubid and len(subset_filterclause) > 0) begin set @command_piece = 'create view ' + @ctsview + ' as select * from MSmerge_contents ' /* Are there any published tables not in this publication? */ if exists (select * from sysmergearticles where pubid <> @pubid and nickname not in (select nickname from sysmergearticles where pubid = @pubid)) set @command_piece = @command_piece + ' where tablenick in (select nickname from sysmergearticles where convert(nchar(36), pubid) = ' + @pubidstr + ')' /* Now select our simple view syntax and we are done with this simple unfiltered case */ select @command_piece return 0 end /* create temp table to insert into and select commands out of */ create table #tempcmd (phase int NOT NULL, step int identity NOT NULL, cmdtext nvarchar(4000) NULL) set @command_piece = 'create view ' + @ctsview + ' as ' insert into #tempcmd (phase, cmdtext) values (1, @command_piece) /* Initialize for loop over articles in this publication */ select @tablenick = min(nickname) from sysmergearticles where pubid = @pubid while @tablenick is not null begin select @objid = objid, @view_type = view_type, @view_name = object_name(sync_objid) from sysmergearticles where pubid = @pubid and nickname = @tablenick select @rowguidcolname = name from syscolumns where id = @objid and columnproperty(id, name, 'isrowguidcol')=1 set @rowguidcolname = QUOTENAME(@rowguidcolname) set @view_name = QUOTENAME(@view_name) set @tablenickstr = convert(nchar(12), @tablenick) if @view_type <> 0 set @command_piece = @union_after_first + ' select * from MSmerge_contents where tablenick = ' + @tablenickstr + ' and rowguid in (select ' + @rowguidcolname + ' from ' + @view_name + ')' else set @command_piece = @union_after_first + ' select * from MSmerge_contents where tablenick = ' + @tablenickstr insert into #tempcmd (phase, cmdtext) values (2, @command_piece) /* Advance to next article and repeat the loop */ select @tablenick = min(nickname) from sysmergearticles where pubid = @pubid and nickname > @tablenick /* make it so that any subsequent selects in the view are preceded by the word UNION */ set @union_after_first = ' UNION ALL ' end /* final steps: select out the text and drop the temp table */ select cmdtext from #tempcmd order by phase, step drop table #tempcmd go exec dbo.sp_MS_marksystemobject sp_MSmakectsview go grant execute on dbo.sp_MSmakectsview to public go -------------------------------------------------------------------------------- --. sp_MSdummyupdate -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSdummyupdate') drop procedure sp_MSdummyupdate 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 or @colv is NULL) 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 grant exec on dbo.sp_MSdummyupdate to public go -------------------------------------------------------------------------------- --. sp_mergecleanupmetadata -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_mergecleanupmetadata') drop procedure sp_mergecleanupmetadata go raiserror('Creating procedure sp_mergecleanupmetadata', 0,1) go create procedure sp_mergecleanupmetadata @publication sysname = '%', @reinitialize_subscriber nvarchar(5) = 'true' AS declare @pubid uniqueidentifier declare @retcode int declare @pubname sysname declare @snapshot_ready int declare @artid uniqueidentifier declare @schematype int declare @schemaversion int declare @schemaguid uniqueidentifier declare @schematext nvarchar(2000) /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) if not exists (select * from sysobjects where name='sysmergearticles') return (1) begin TRAN declare #per_publication CURSOR LOCAL FAST_FORWARD for select pubid from sysmergepublications where LOWER(publisher)=LOWER(@@SERVERNAME) and publisher_db=db_name() and name like @publication open #per_publication fetch #per_publication into @pubid while @@fetch_status<>-1 begin select @pubname=name, @snapshot_ready=snapshot_ready from sysmergepublications where pubid=@pubid if @publication <> '%' and exists (select * from sysmergearticles where pubid<>@pubid and objid in (select objid from sysmergearticles where pubid=@pubid)) begin raiserror(21287, 16, -1, @pubname) goto FAILURE end /* Only do this when snapshot has been ran before this operation */ if @snapshot_ready>0 begin if LOWER(@reinitialize_subscriber)='true' begin exec @retcode = sp_reinitmergesubscription @publication=@pubname if @@ERROR<>0 or @retcode<>0 begin close #per_publication deallocate #per_publication goto FAILURE end update sysmergepublications set snapshot_ready=2 where pubid=@pubid if @@ERROR<>0 begin close #per_publication deallocate #per_publication goto FAILURE end end else 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 @artid = newid() set @schematype = 16 /* metadata cleanup */ select @schematext = 'exec dbo.sp_MScleanup_metadata '+ '''' + convert(nchar(36),@pubid) + '''' exec @retcode=sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext if @@ERROR<>0 or @retcode<>0 begin close #per_publication deallocate #per_publication goto FAILURE end end end delete from MSmerge_contents where tablenick in (select nickname from sysmergearticles where pubid=@pubid) delete from MSmerge_tombstone where tablenick in (select nickname from sysmergearticles where pubid=@pubid) fetch next from #per_publication into @pubid end close #per_publication deallocate #per_publication COMMIT TRAN return (0) FAILURE: if @@TRANCOUNT = 1 ROLLBACK TRANSACTION else COMMIT TRANSACTION return (1) GO exec dbo.sp_MS_marksystemobject sp_mergecleanupmetadata go grant execute on dbo.sp_mergecleanupmetadata to public go -------------------------------------------------------------------------------- --. sp_MScleanuptask -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MScleanuptask') drop procedure sp_MScleanuptask 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 declare @before_name sysname declare @procname sysname 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) -- If there are any before image tables, clean them up too declare bi_cursor CURSOR LOCAL FAST_FORWARD for select distinct OBJECT_NAME(before_image_objid) from sysmergearticles where OBJECT_NAME(before_image_objid) is NOT NULL FOR READ ONLY open bi_cursor fetch next from bi_cursor into @before_name while (@@fetch_status <> -1) begin set @procname = @before_name + '_clean ' exec @procname @mingen fetch next from bi_cursor into @before_name end close bi_cursor deallocate bi_cursor return (0) go grant exec on dbo.sp_MScleanuptask to public go -------------------------------------------------------------------------------- --. sp_MSenumdeletesmetadata -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSenumdeletesmetadata') drop procedure sp_MSenumdeletesmetadata go raiserror('Creating procedure sp_MSenumdeletesmetadata', 0,1) go CREATE PROCEDURE sp_MSenumdeletesmetadata( @pubid uniqueidentifier, @maxrows int, @genlist varchar(1000), @tablenick int, @rowguid uniqueidentifier, @filter_partialdeletes int = 0) as declare @tnstring nvarchar(12) declare @rgstring nvarchar(38) declare @pubidstr nvarchar(38) declare @tablenick_qual nvarchar(100) /* ** 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 the filter_partialdeletes is NOT set, include all types of tombstones, else filter the type = 5 ones */ if (@filter_partialdeletes = 0) set @tablenick_qual = ' and ts.tablenick = sm.nickname ' else set @tablenick_qual = ' and ts.tablenick = sm.nickname and ts.type <> 5' 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 + @tablenick_qual + ' 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 + @tablenick_qual + ' order by tablenick desc, rowguid asc' ) end IF @@ERROR <>0 begin return (1) end return (0) go grant exec on dbo.sp_MSenumdeletesmetadata to public go -------------------------------------------------------------------------------- --. sp_MSenumpartialdeletes -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSenumpartialdeletes') drop procedure sp_MSenumpartialdeletes go raiserror('Creating procedure sp_MSenumpartialdeletes', 0,1) go CREATE PROCEDURE sp_MSenumpartialdeletes (@maxrows int, @tablenick int, @rowguid uniqueidentifier, @tablenotbelongs nvarchar(255), @bookmark int = NULL) as declare @tnstring nvarchar(12) declare @rgstring nvarchar(38) declare @lowrangestr nvarchar(12) declare @highrangestr nvarchar(12) /* ** To public. */ if (not exists(select * from sysobjects where name = 'MSmerge_contents')) begin RAISERROR(20054 , 16, -1) return (1) end /* Always do the set rowcount, we never want to return too many rows */ set rowcount @maxrows if (@tablenick < 1) begin execute ('select tablenick, rowguid, COALESCE (generation, 0), lineage, type, bookmark from ' + @tablenotbelongs + ' order by tablenick desc, rowguid asc' ) IF @@ERROR <>0 begin return (1) end end else begin set @tnstring = convert(nchar, @tablenick) set @rgstring = '''' + convert(nchar(36), @rowguid) + '''' /* ** If a 7.0 SP1 Merge agent is calling this sp, it passed a valid bookmark parameter ** Use the bookmark column in the ##belongs_<> table to retrieve the next batch of rows */ if @bookmark is NOT NULL begin set @lowrangestr = convert(nchar, @bookmark) set @highrangestr = convert(nchar, (@bookmark + @maxrows)) execute ('select tablenick, rowguid, COALESCE (generation, 0), lineage, type, bookmark from ' + @tablenotbelongs + ' where bookmark > ' + @lowrangestr + ' and bookmark <= ' + @highrangestr + ' order by bookmark' ) if @@ERROR<>0 begin return (1) end end /* ** Backward copatibilty mode : If a 7.0 Merge agent is calling this sp, it will pass a NULL bookmark parameter ** Use the rowguid and set rowcount to retrieve the next batch of rows */ else begin 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' ) IF @@ERROR <>0 begin return (1) end end end return (0) go grant exec on dbo.sp_MSenumpartialdeletes to public go -------------------------------------------------------------------------------- --. sp_MSenumpartialchanges -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSenumpartialchanges') drop procedure sp_MSenumpartialchanges 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 @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) set rowcount @maxrows 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 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 grant exec on dbo.sp_MSenumpartialchanges to public go -------------------------------------------------------------------------------- --. sp_MSinitdynamicsubscriber -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSinitdynamicsubscriber') drop procedure sp_MSinitdynamicsubscriber go raiserror('Creating procedure sp_MSinitdynamicsubscriber', 0,1) go CREATE PROCEDURE sp_MSinitdynamicsubscriber (@maxrows int, @tablenick int, @rowguid uniqueidentifier, @pubid uniqueidentifier = NULL) as declare @retcode smallint declare @procname nvarchar(258) /* ** To public. */ if (@tablenick is null) begin RAISERROR(14043, 16, -1, '@tablenick') return (1) end select @procname = view_sel_proc from sysmergearticles where pubid = @pubid and nickname = @tablenick exec @retcode = @procname @tablenick, @maxrows, @rowguid if @@ERROR<>0 or @retcode<>0 begin return (1) end return (0) go grant exec on dbo.sp_MSinitdynamicsubscriber to public go -------------------------------------------------------------------------------- --. sp_MSgetrowmetadata -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSgetrowmetadata') drop procedure sp_MSgetrowmetadata go 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 set @type = 4 exec @retcode = @procname @type = @type output, @rowguid=@rowguid if @@ERROR <>0 return (1) if (@type = 3) begin select @type = 2, @generation = generation, @lineage = lineage, @colv = colv1 from MSmerge_contents where tablenick = @tablenick and rowguid = @rowguid end end -- DEBUG insert into master.dbo.debuglog(tablenick, rowguid, type, twhen, comment) values -- DEBUG (@tablenick, @rowguid, @type, getdate(), 'sp_MSgetrowmetadata') return (0) go grant exec on dbo.sp_MSgetrowmetadata to public go -------------------------------------------------------------------------------- --. sp_MSgetmetadatabatch -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSgetmetadatabatch') drop procedure sp_MSgetmetadatabatch go raiserror('Creating procedure sp_MSgetmetadatabatch', 0,1) go CREATE PROCEDURE sp_MSgetmetadatabatch (@pubid uniqueidentifier, @tablenickarray varbinary(2000), @rowguidarray varbinary(8000) ) as declare @tablenick int declare @rowguid uniqueidentifier declare @generation int declare @type tinyint declare @lineage varbinary(255) declare @colv varbinary(2048) declare @retcode smallint declare @saverr int declare @rc int declare @tnlength int declare @tnoffset int declare @guidoffset int /* ** To public. */ if (@tablenickarray is null) begin RAISERROR(14043, 16, -1, '@tablenick') return (1) end if (@rowguidarray is null) begin RAISERROR(14043, 16, -1, '@rowguid') return (1) end -- create temp table for returning results create table #meta_batch(idx int identity, generation int, type tinyint, lineage varbinary(255), colv varbinary(2048)) -- initialize offsets and length for walking through arrays set @tnoffset = 1 set @guidoffset = 1 set @tnlength = datalength(@tablenickarray) -- walk through arrays and populate temp table while (@tnoffset < @tnlength) begin set @tablenick = substring(@tablenickarray, @tnoffset, 4) set @rowguid = substring(@rowguidarray, @guidoffset, 16) set @generation = 0 set @type = 0 set @lineage = NULL set @colv = NULL exec @rc = sp_MSgetrowmetadata @tablenick, @rowguid, @generation output, @type output, @lineage output, @colv output, @pubid if @rc <> 0 return @rc -- insert values into temp table insert into #meta_batch (generation, type, lineage, colv) values (@generation, @type, @lineage, @colv) -- bump up offsets for next time through loop set @tnoffset = @tnoffset + 4 set @guidoffset = @guidoffset + 16 end -- select out our result set select generation, type, lineage, colv from #meta_batch order by idx drop table #meta_batch return (0) go grant exec on dbo.sp_MSgetmetadatabatch to public go -------------------------------------------------------------------------------- --. sp_MSupdateschemachange -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSupdateschemachange') drop procedure sp_MSupdateschemachange 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 schemaversion = @schemaversion if @@error <> 0 begin RAISERROR(20054 , 16, -1) return (1) end return (0) go grant exec on dbo.sp_MSupdateschemachange to public go -------------------------------------------------------------------------------- --. sp_MSadd_mergereplcommand -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSadd_mergereplcommand') drop procedure sp_MSadd_mergereplcommand 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 + '"' -- Put outter quotes if running on NT if ((platform() & 0x1) = 0x1) select @delcmd = '" ' + @delcmd + ' "' 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 /* ** change last_validate column of sysmergesubscription entry that represents the publication */ if (@schematype = 7) begin update sysmergesubscriptions set last_validated=getdate() where pubid=@pubid and subid=@pubid IF @@ERROR <> 0 begin RAISERROR(20054 , 16, -1) RETURN (1) end end return (0) go grant exec on dbo.sp_MSadd_mergereplcommand to public go -------------------------------------------------------------------------------- --. sp_MSsetreplicainfo -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSsetreplicainfo') drop procedure sp_MSsetreplicainfo 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 /* ** SQL Server */ SELECT @repid = subid FROM sysmergesubscriptions WHERE srvid = @srvid and db_name = @db_name and pubid = @pubid END ELSE IF (@datasource_type = 4) or (@datasource_type = 5) BEGIN /* ** Exchange or Oracle */ SELECT @repid = subid FROM sysmergesubscriptions WHERE srvid = @srvid and pubid = @pubid END ELSE BEGIN /* ** Jet */ 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 grant exec on dbo.sp_MSsetreplicainfo to public go -------------------------------------------------------------------------------- --. sp_MSmakeconflictinsertproc -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSmakeconflictinsertproc') drop procedure sp_MSmakeconflictinsertproc 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 @header nvarchar(4000) declare @vallist nvarchar(4000) declare @qualname nvarchar(266) declare @argname nvarchar(258) declare @noset bit declare @wherepc nvarchar(255) declare @id int declare @colname nvarchar(258) declare @typename nvarchar(258) declare @colid smallint declare @status tinyint declare @len smallint declare @prec smallint declare @scale int declare @retcode smallint declare @sys_loop bit declare @old_colname nvarchar(258) declare @create_time_col nvarchar(5) set nocount on select @sys_loop = 0 set @create_time_col = NULL 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) -- 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) select @header = 'Create procedure dbo.' + @procname + ' ( ' insert into #tempcmd (phase, cmdtext) values (0, @header) select @colid = min(colid) from syscolumns where id = @id and iscomputed <>1 and type_name(xtype) <> 'timestamp' and ((name not in (select name from syscolumns where id=@basetableid) and @sys_loop =1) OR (name in (select name from syscolumns where id=@basetableid) and @sys_loop =0)) 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 /* ** Get the column list from the conflict_table schema and filter it with table view for vertical partitioning */ Reverse_Order: while (@colname is not null) begin set @noset = 0 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) begin select @noset =1 set @wherepc = ' where rowguidcol = ' + @argname end else if (@colname = 'origin_datasource') begin select @wherepc =@wherepc + ' and origin_datasource = ' + @argname set @noset =1 end set @old_colname = @colname set @colname = QUOTENAME(@colname) if @arglist is null begin set @arglist = @argname + ' ' + @typename --give default value of NULL to new merge columns for backward compatibility concern insert into #tempcmd (phase, cmdtext) values (3, @colname) set @vallist = @argname if @noset=0 insert into #tempcmd (phase, cmdtext) values (1, @colname + ' = ' + @argname) end else begin if len(@arglist)>3700 begin insert into #tempcmd (phase, cmdtext) values (0, @arglist) select @arglist = ' ' end set @arglist = @arglist + ', ' + @argname + ' ' + @typename if @sys_loop = 1 and @old_colname not in ('origin_datasource','conflict_type','reason_code','reason_text', 'pubid') begin select @arglist=@arglist + ' = NULL' if @old_colname='create_time' select @create_time_col=@argname end insert into #tempcmd (phase, cmdtext) values (3, ',' + @colname) set @vallist = @vallist + ', ' + @argname if @noset =0 begin if exists (select * from #tempcmd where phase=1) insert into #tempcmd (phase, cmdtext) values (1, ',' + @colname + ' = ' + @argname) else insert into #tempcmd (phase, cmdtext) values (1, @colname + ' = ' + @argname) end end NEXT_COL: select @colid = min(colid) from syscolumns where id = @id and colid>@colid and iscomputed <>1 and type_name(xtype) <> 'timestamp' and ((name not in (select name from syscolumns where id=@basetableid) and @sys_loop =1) OR (name in (select name from syscolumns where id=@basetableid) and @sys_loop =0)) 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 if @sys_loop = 0 begin select @sys_loop = 1 select @colid = min(colid) from syscolumns where id = @id and iscomputed <>1 and type_name(xtype) <> 'timestamp' and ((name not in (select name from syscolumns where id=@basetableid) and @sys_loop =1) OR (name in (select name from syscolumns where id=@basetableid) and @sys_loop =0)) 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 goto Reverse_Order end -- now create the procedure select @procname = QUOTENAME(@procname) insert into #tempcmd (phase, cmdtext) values (0, @arglist) select @header = ') as' insert into #tempcmd (phase, cmdtext) values (0, @header) select @header = ' ' -- for ease of expansion here in case we add new merge columns in conflict tables. if @create_time_col is not NULL select @header = @header + ' select ' + @create_time_col + ' = getdate() ' select @header = @header + ' update ' + @qualname + ' set ' insert into #tempcmd (phase, cmdtext) values (0, @header) select @header = @wherepc + ' if (@@rowcount = 0) insert into ' + @qualname + ' (' insert into #tempcmd (phase, cmdtext) values (2, @header) select @header = ') values (' + @vallist + ')' insert into #tempcmd (phase, cmdtext) values (4, @header) -- 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 grant exec on dbo.sp_MSmakeconflictinsertproc to public go -------------------------------------------------------------------------------- --. sp_MSgetconflictinsertproc -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSgetconflictinsertproc') drop procedure sp_MSgetconflictinsertproc go raiserror('Creating procedure sp_MSgetconflictinsertproc', 0,1) go CREATE PROCEDURE sp_MSgetconflictinsertproc ( @artid uniqueidentifier, @output int = 1 ) AS declare @conflict_table sysname declare @dbname 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 @command nvarchar(4000) 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) set @dbname = db_name() if @owner is NULL set @command = 'sp_MSmakeconflictinsertproc ' + QUOTENAME(@conflict_table) + ' , NULL, ' + @conflict_proc + ' , ' + convert(nvarchar,@basetableid) else set @command = 'sp_MSmakeconflictinsertproc ' + QUOTENAME(@conflict_table) + ' , ' + QUOTENAME(@owner) + ' , ' + @conflict_proc + ' , ' + convert(nvarchar,@basetableid) exec @retcode = master..xp_execresultset @command, @dbname if @@ERROR<>0 OR @retcode<>0 begin return (1) end exec @retcode = dbo.sp_MS_marksystemobject @conflict_proc if @@ERROR<>0 return (1) exec ('grant exec on ' + @conflict_proc + ' to public') 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 grant exec on dbo.sp_MSgetconflictinsertproc to public go -------------------------------------------------------------------------------- --. sp_MSdelrow -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSdelrow') drop procedure sp_MSdelrow go 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) + '''' -- DEBUG insert into master.dbo.debuglog(tablenick, rowguid, type, twhen, comment) values -- DEBUG (@tablenick, @rowguid, @metadata_type, getdate(), 'sp_MSdelrow') -- Are we just changing the type of a tombstone? -- This routine is only called for Upload; won't be type 5 (remove from partial) unless -- subscriber has a user delete and found an existing metadata type of 5 here. -- In that case, set delete type to 1 and update generation, reason text too. if (@metadata_type = 5 and exists (select * from MSmerge_tombstone where rowguid = @rowguid and tablenick = @tablenick)) begin set @reason = formatmessage (20562) -- User delete update MSmerge_tombstone set type = 1, reason = @reason, generation = @generation, lineage = @lineage_new 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, generation = @generation 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 grant exec on dbo.sp_MSdelrow to public go -------------------------------------------------------------------------------- --. sp_MSsetartprocs -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSsetartprocs') drop procedure sp_MSsetartprocs go raiserror('Creating procedure sp_MSsetartprocs', 0,1) go 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, @objid 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 grant exec on dbo.sp_MSsetartprocs to public go -------------------------------------------------------------------------------- --. sp_MSexpandbelongs -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSexpandbelongs') drop procedure sp_MSexpandbelongs go raiserror('Creating procedure sp_MSexpandbelongs', 0,1) go 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 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 exists (select * from #belong where tablenick = join_nickname and flag < join_filterid) end return (0) go grant exec on dbo.sp_MSexpandbelongs to public go -------------------------------------------------------------------------------- --. sp_MSexpandnotbelongs -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSexpandnotbelongs') drop procedure sp_MSexpandnotbelongs go raiserror('Creating procedure sp_MSexpandnotbelongs', 0,1) go 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 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 exists (select * from #notbelong where tablenick = join_nickname and flag < join_filterid) end go grant exec on dbo.sp_MSexpandnotbelongs to public go -------------------------------------------------------------------------------- --. sp_MSsetupbelongs -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSsetupbelongs') drop procedure sp_MSsetupbelongs go raiserror('Creating procedure sp_MSsetupbelongs', 0,1) go 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 @belongs_uniquename sysname declare @notbelongsname sysname declare @notbelongs_uniquename sysname declare @artnick int declare @artnickstr nvarchar(10) declare @artviewobjid int declare @before_view_objid int declare @before_view_name sysname declare @procname sysname declare @sync_objid int -- DEBUG declare @belongcnt int -- DEBUG declare @nb_cnt int 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 declare @dynamic_join_cnt int /* ** To public */ set @temp_view = 2 -- DEBUG insert into master.dbo.debuglog2 (publisher, pubdb, hostname, twhen, commongen, belong_cnt, nb_cnt, genlist) values -- DEBUG (@publisher, @publisher_db, host_name(), getdate(), @commongen, NULL, NULL, @genlist) select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db set @commongenstr = convert(nchar(12), @commongen) select @dynamic_join_cnt = count(*) from sysmergesubsetfilters where pubid = @pubid and (UPPER(join_filterclause) like '%USER_%NAME%' or UPPER(join_filterclause) like '%USER_%ID%' or UPPER(join_filterclause) like '%SESSION_USER%' or UPPER(join_filterclause) like '%SYSTEM_USER%') /* 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 set @belongs_uniquename = 'bunique_' + @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, skippedexpand 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 (tablenick int NOT NULL, rowguid uniqueidentifier NOT NULL, flag int NOT NULL, partchangegen int null, joinchangegen int null, type int default 5) create index #indnbelong on #notbelong (tablenick, rowguid) create table #genlist (generation int) exec ('insert into #genlist select distinct generation from MSmerge_genhistory where generation in (' + @genlist + ')') set @notbelongsname = '##notbelong' + @rowguidstr set @notbelongs_uniquename = 'nbunique_' + @rowguidstr exec @retcode = dbo.sp_MSuniquetempname @notbelongsname, @notbelongsname out IF @@ERROR<>0 OR @retcode<>0 return (1) exec ('create table ' + @notbelongsname + ' (bookmark int identity primary key NOT NULL, 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 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, @sync_objid=sync_objid, @before_view_objid = before_view_objid 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 return (1) 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 /* Put changes in #notbelong that aren't in #belong and have a relevant partchangegen */ -- If publication has before image tables, we should screen changes using the before image tables if @before_view_objid is not null begin set @before_view_name = OBJECT_NAME(@before_view_objid) execute ('insert into #notbelong (tablenick, rowguid, flag, partchangegen, joinchangegen) select tablenick, c.rowguid, 0, partchangegen, joinchangegen from MSmerge_contents c, #genlist g where c.generation = g.generation and partchangegen > ' + @commongenstr + ' and tablenick = ' + @artnickstr + ' and rowguid in (select ' + @rgcol + ' from ' + @before_view_name + ') and rowguid not in (select rowguid from #belong)') if @@ERROR <>0 return (1) /* Add tombstones to ##notbelong */ execute ('insert into #notbelong (tablenick, rowguid, flag, partchangegen, joinchangegen, type) select tablenick, rowguid, 0, generation, generation, type from MSmerge_tombstone where tablenick = ' + @artnickstr + ' and rowguid in (select ' + @rgcol + ' from ' + @before_view_name + ') and generation in (' + @genlist + ' ) ') if @@ERROR <>0 return (1) end else begin insert into #notbelong (tablenick, rowguid, flag, partchangegen, joinchangegen) select tablenick, c.rowguid, 0, partchangegen, joinchangegen from MSmerge_contents c, #genlist g where c.generation = g.generation and partchangegen > @commongen and tablenick = @artnick and rowguid not in (select rowguid from #belong) if @@ERROR <>0 return (1) execute ('insert into #notbelong (tablenick, rowguid, flag, partchangegen, joinchangegen, type) select tablenick, rowguid, 0, generation, generation, type from MSmerge_tombstone where tablenick = ' + @artnickstr + ' and generation in (' + @genlist + ' ) ') if @@ERROR <>0 return (1) 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 /* 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, skippedexpand = 1 where ((joinchangegen is null or 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 distinct 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 order by b.tablenick, b.rowguid') if @@ERROR <>0 return (1) /* If subscriber is sql server, we don't have to expand belongs */ if @subissql = 0 or @dynamic_join_cnt > 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 distinct b.tablenick, b.rowguid, coalesce (c.generation, t.generation), coalesce(c.lineage, t.lineage), b.type from #notbelong b left outer join MSmerge_contents c on c.tablenick = b.tablenick and c.rowguid = b.rowguid left outer join MSmerge_tombstone t on t.tablenick = b.tablenick and t.rowguid = b.rowguid order by b.tablenick DESC, b.rowguid ASC') if @@ERROR <>0 return (1) -- DEBUG select @belongcnt = count(*) from #belong -- DEBUG select @nb_cnt = count(*) from #notbelong drop table #notbelong -- DEBUG insert into master.dbo.debuglog2 (publisher, pubdb, hostname, twhen, commongen, belong_cnt, nb_cnt, genlist) values -- DEBUG (@publisher, @publisher_db, host_name(), getdate(), @commongen, @belongcnt, @nb_cnt, @genlist) if not exists (select * from #belong) select @belongsname, @notbelongsname, -1 else select distinct @belongsname, @notbelongsname, tablenick from #belong drop table #belong return (0) go grant exec on dbo.sp_MSsetupbelongs to public go -------------------------------------------------------------------------------- --. sp_MSexclause -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSexclause') drop procedure sp_MSexclause go raiserror('Creating procedure sp_MSexclause', 0,1) go create proc sp_MSexclause @tablenick int as set nocount on declare @clause nvarchar(4000) declare @filterid int declare @joinnick int declare @jointable nvarchar(258) declare @table sysname declare @basetable nvarchar(258) declare @filter_clause nvarchar(2000) exec sp_MStablenamefromnick @tablenick, @basetable out select @table = QUOTENAME(name) from sysobjects where id in (select objid from sysmergearticles where nickname = @tablenick) declare f_c CURSOR LOCAL FAST_FORWARD for select art_nickname, join_filterclause from sysmergesubsetfilters where join_nickname = @tablenick FOR READ ONLY open f_c fetch next from f_c into @joinnick, @filter_clause while (@@fetch_status <> -1) begin exec sp_MStablenamefromnick @joinnick, @jointable out -- As helper proc for sp_MSmakeinsertproc, we can insert directly to the -- temp table as we build up more commands for the insert proc. -- Our commands are part of phase 8... set @clause = ' if @has_rows = 0 select @has_rows = count(*) from ' + @basetable + ', ' + @jointable + ' where ' + @filter_clause + ' and ' + @table + '.rowguidcol = @rowguid ' insert into #tempcmd (phase, cmdtext) values (8, @clause) fetch next from f_c into @joinnick, @filter_clause end close f_c deallocate f_c go grant exec on dbo.sp_MSexclause to public go -------------------------------------------------------------------------------- --. sp_MSmakeinsertproc -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSmakeinsertproc') drop procedure sp_MSmakeinsertproc go raiserror('Creating procedure sp_MSmakeinsertproc', 0,1) go 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 declare @has_rows int set nocount on set @has_rows = 0 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) -- if we already have a tombstone for this row, (especially a remove from partial) then -- make sure we will set the generation so that it goes on down to subscribers of republishers set @cmdpiece = 'if exists (select * from MSmerge_tombstone where tablenick = @tablenick and rowguid = @rowguid) set @has_rows = 1' 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 if @metadata_type = 1 or @metadata_type = 5 begin if not exists (select * from MSmerge_tombstone where tablenick = @tablenick and rowguid = @rowguid and lineage = @lineage_old) begin set @success = 2 commit transaction return 0 end end 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) -- Add in pieces that check for inserting a row that instantly means other rows need to be downloaded -- If we insert such a row, set the generation and partchangegen so that we will download everything -- that needs to go. exec sp_MSexclause @tablenick set @cmdpiece = 'if @has_rows > 0 update MSmerge_contents set generation = 0, partchangegen = 0 where rowguid = @rowguid and tablenick = @tablenick' 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 select @cmdpiece = ',@metadata_type tinyint = NULL, @lineage_old varbinary(255) = NULL' insert into #tempcmd (phase, cmdtext) values (1, @cmdpiece) -- 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 -------------------------------------------------------------------------------- --. sp_MSmakeupdateproc -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSmakeupdateproc') drop procedure sp_MSmakeupdateproc go raiserror('Creating procedure sp_MSmakeupdateproc', 0,1) go 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 set nocount on 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 ( ' + @varname + ' is null and ' + @argname + ' is null) 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 grant exec on dbo.sp_MSmakeupdateproc to public go -------------------------------------------------------------------------------- --. sp_MSmakeselectproc -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSmakeselectproc') drop procedure sp_MSmakeselectproc 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 output, @rowguid uniqueidentifier=NULL) AS declare @retcode int declare @objid int set nocount on 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 begin set @type = 0 if exists (select * from ' + @qualified_name + ' where rowguidcol = @rowguid) set @type = 3 return 0 end 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 grant exec on dbo.sp_MSmakeselectproc to public go -------------------------------------------------------------------------------- --. sp_MSexpandsubsnb -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSexpandsubsnb') drop procedure sp_MSexpandsubsnb 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) declare @join_unique_key int /* 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, @join_unique_key = join_unique_key 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. ** Only join filters that are non unique need to contract the ** NOTBELONGS table - */ if @@rowcount <> 0 and @join_unique_key = 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 grant exec on dbo.sp_MSexpandsubsnb to public go -------------------------------------------------------------------------------- --. sp_MSdelsubrows -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSdelsubrows') drop procedure sp_MSdelsubrows 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, @rowsdeleted INT = NULL OUTPUT) 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 /* By default this sp should delete exactly one row */ set @rowsdeleted = 1 /* ** 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) + '''' -- DEBUG insert into master.dbo.debuglog(tablenick, rowguid, type, twhen, comment) values -- DEBUG (@tablenick, @rowguid, @metadata_type, getdate(), 'sp_MSdelsubrows') -- 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 return @success end -- Are we just changing the type of a tombstone? if (@metadata_type = 1 and exists (select * from MSmerge_tombstone where rowguid = @rowguid and tablenick = @tablenick)) begin set @reason = formatmessage (20562) -- User delete 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 (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 @rowsdeleted = count(*) from #notbelong 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 grant exec on dbo.sp_MSdelsubrows to public go -------------------------------------------------------------------------------- --. sp_MSmakeviewproc -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSmakeviewproc') drop procedure sp_MSmakeviewproc go raiserror('Creating procedure sp_MSmakeviewproc', 0,1) go create procedure sp_MSmakeviewproc (@viewname sysname, @ownername sysname, @procname nvarchar(290), @rgcol sysname, @source_id int) as declare @retcode smallint declare @varname nvarchar(10) declare @cmdpiece nvarchar(4000) declare @column_list nvarchar(4000) declare @col_name sysname set nocount on if EXISTS (select name from syscolumns where id=@source_id and iscomputed=1) BEGIN select @column_list = '' DECLARE column_cursor CURSOR LOCAL FAST_FORWARD FOR select name from syscolumns where id=@source_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 = 'v.rowguid' --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 = '*' select @procname=QUOTENAME(@procname) set @cmdpiece = 'create procedure dbo.' + @procname + ' (@tablenick int, @max_rows int = NULL, @guidlast uniqueidentifier = NULL) AS set nocount on set rowcount 0 if @max_rows is not null begin -- used to select data for initial pop. of subscriber for dynamic filtered publication set rowcount @max_rows declare @lin varbinary (255) declare @cv varbinary (2048) declare @replnick int declare @objid int declare @ccols int select @objid = objid from sysmergearticles where nickname = @tablenick select @ccols = max(colid) from syscolumns where id = @objid exec dbo.sp_MSgetreplnick @nickname = @replnick out if (@@error <> 0) or @replnick IS NULL begin RAISERROR (14055, 11, -1) RETURN(1) end set @lin = { fn UPDATELINEAGE(0x0, @replnick) } set @cv = { fn INITCOLVS(@ccols, @replnick) } select @tablenick, v.' + @rgcol + ', coalesce (c.generation,1), coalesce (c.lineage, @lin), coalesce (c.colv1, @cv), ' + @column_list + ' from ' + QUOTENAME(@ownername) + '.' + QUOTENAME(@viewname) + ' v left outer join MSmerge_contents c on v.' + @rgcol + ' = c.rowguid and c.tablenick = @tablenick where v.' + @rgcol + ' > @guidlast order by v.' + @rgcol + ' return (1) end insert into #belong (tablenick, rowguid, flag, partchangegen, joinchangegen) select ct.tablenick, ct.rowguid, 0, ct.partchangegen, ct.joinchangegen from MSmerge_contents ct, #genlist g, ' + QUOTENAME(@ownername) + '.' + QUOTENAME(@viewname) + ' v where ct.tablenick = @tablenick and (ct.generation = g.generation or ct.partchangegen = g.generation) and ct.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 grant exec on dbo.sp_MSmakeviewproc to public go -------------------------------------------------------------------------------- --. sp_MScreatebeforetable -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MScreatebeforetable') drop procedure sp_MScreatebeforetable go raiserror('Creating procedure sp_MScreatebeforetable', 0,1) go create procedure sp_MScreatebeforetable @objid int AS declare @command nvarchar(4000) declare @objidstr nvarchar(12) declare @dbname sysname declare @oldname sysname declare @newname sysname declare @nameguid uniqueidentifier declare @retcode int declare @tablenick int set nocount on -- If no publication including this table needs before images, just return if not exists (select * from sysmergepublications p, sysmergearticles a where a.objid = @objid and p.pubid = a.pubid and p.keep_before_values = 1) return (0) select @tablenick = max(nickname) from sysmergearticles where objid = @objid if @tablenick is null return (1) -- If a before image table already exists for this table, we need to drop it and create a new one select @oldname = max(o.name) from sysobjects o, sysmergearticles a where a.objid = @objid and o.id = a.before_image_objid if @oldname is not null begin exec @retcode = sp_MShelpalterbeforetable @objid, @oldname if @retcode <> 0 return (1) return 0 end -- If this table is not involved with any filters or join filters, don't bother if not exists (select * from sysmergesubsetfilters where art_nickname = @tablenick or join_nickname = @tablenick) and not exists (select * from sysmergearticles where nickname = @tablenick and datalength (subset_filterclause) > 1) return 0 -- Generate a unique name for our new table set @nameguid = newid() exec @retcode = dbo.sp_MSguidtostr @nameguid, @newname out set @newname = 'MS_bi' + @newname if @@ERROR <>0 OR @retcode <>0 return (1) -- Call xp_execresultset with helper function command set @objidstr = convert(nvarchar(12), @objid) set @dbname = db_name() set @command = 'exec dbo.sp_MShelpcreatebeforetable ' + @objidstr + ', ''' + @newname + '''' exec @retcode = master..xp_execresultset @command, @dbname if @retcode <> 0 return (1) update sysmergearticles set before_image_objid = object_id( @newname ) where objid = @objid -- Now create a cleanup proc and grant execute on it.. set @command = 'create procedure ' + @newname + '_clean @mingen int AS delete from ' + @newname + ' where generation < @mingen ' exec (@command) set @command = 'grant execute on ' + @newname + '_clean to public' exec (@command) go -------------------------------------------------------------------------------- --. sp_MShelpcreatebeforetable -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MShelpcreatebeforetable') drop procedure sp_MShelpcreatebeforetable go raiserror('Creating procedure sp_MShelpcreatebeforetable', 0,1) go create procedure sp_MShelpcreatebeforetable @objid int, @newname sysname AS declare @command nvarchar(1000) declare @retcode int declare @include int declare @tablenick int declare @colpat nvarchar(130) declare @colname sysname declare @typename sysname declare @colid smallint declare @colidstr nvarchar(3) declare @status tinyint declare @len smallint declare @prec smallint declare @scale int declare @isnullable tinyint set nocount on select @tablenick = max(nickname) from sysmergearticles where objid = @objid if @tablenick is null return (1) -- 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) set @command = 'create table ' + @newname + '(' insert into #tempcmd (phase, cmdtext) values (1, @command) -- Loop over the columns and see which ones we include declare col_cursor CURSOR LOCAL FAST_FORWARD for select name, status, type_name(xtype), length, prec, scale, isnullable, colid from syscolumns where id = @objid and iscomputed <> 1 and type_name(xtype) <> 'timestamp' order by colid FOR READ ONLY open col_cursor fetch next from col_cursor into @colname, @status, @typename, @len, @prec, @scale, @isnullable, @colid while (@@fetch_status <> -1) begin set @include = 0 set @colpat = '%' + @colname + '%' if columnproperty( @objid, @colname , 'isrowguidcol')=1 begin set @include = 1 end else begin -- does updating this column change membership in a partial replica? if exists (select * from sysmergearticles where objid = @objid and subset_filterclause like @colpat) set @include = 1 else if exists (select * from sysmergesubsetfilters where art_nickname = @tablenick and join_filterclause like @colpat) set @include = 1 else if exists (select * from sysmergesubsetfilters where join_nickname = @tablenick and join_filterclause like @colpat) set @include = 1 end -- If we want this column, map its type and insert a row to temp table if @include = 1 begin if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes set @len = @len/2 exec @retcode = dbo.sp_MSmaptype @typename out, @len, @prec, @scale if @@ERROR<>0 or @retcode<>0 return (1) set @colname = QUOTENAME(@colname) if @isnullable = 1 set @command = @colname + ' ' + @typename + ' NULL, ' else set @command = @colname + ' ' + @typename + ' NOT NULL, ' -- Insert the part of create table command for this column insert into #tempcmd (phase, cmdtext) values (1, @command) -- Insert a create index command set @colidstr =convert(nvarchar(3), @colid) set @command = 'create index ' + @newname + '_' + @colidstr + ' on ' + @newname + ' (' + @colname + ') ' insert into #tempcmd (phase, cmdtext) values (2, @command) end /* Repeat the loop with next column */ fetch next from col_cursor into @colname, @status, @typename, @len, @prec, @scale, @isnullable, @colid end close col_cursor deallocate col_cursor -- Insert last column, generation set @command = 'generation int NOT NULL) ' insert into #tempcmd (phase, cmdtext) values (1, @command) set @command = 'create index ' + @newname + '_gen on ' + @newname + '(generation) ' insert into #tempcmd (phase, cmdtext) values (2, @command) select cmdtext from #tempcmd order by phase, step go -------------------------------------------------------------------------------- --. sp_MShelpalterbeforetable -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MShelpalterbeforetable') drop procedure sp_MShelpalterbeforetable go raiserror('Creating procedure sp_MShelpalterbeforetable', 0,1) go create procedure sp_MShelpalterbeforetable @objid int, @biname sysname AS declare @command nvarchar(1000) declare @retcode int declare @include int declare @tablenick int declare @colpat nvarchar(130) declare @colname sysname declare @typename sysname declare @colid smallint declare @colidstr nvarchar(3) declare @status tinyint declare @len smallint declare @prec smallint declare @scale int declare @isnullable tinyint declare @bi_objid int set nocount on select @tablenick = max(nickname) from sysmergearticles where objid = @objid if @tablenick is null return (1) select @bi_objid = OBJECT_ID(@biname) -- Loop over the columns and see which ones we include declare col_cursor CURSOR LOCAL FAST_FORWARD for select name, status, type_name(xtype), length, prec, scale, isnullable, colid from syscolumns where id = @objid and iscomputed <> 1 and type_name(xtype) <> 'timestamp' order by colid FOR READ ONLY open col_cursor fetch next from col_cursor into @colname, @status, @typename, @len, @prec, @scale, @isnullable, @colid while (@@fetch_status <> -1) begin set @include = 0 set @colpat = '%' + @colname + '%' -- Is this column already in the before image table? if exists (select * from syscolumns where id = @bi_objid and name = @colname) begin goto fetchnext end -- does updating this column change membership in a partial replica? if exists (select * from sysmergearticles where objid = @objid and subset_filterclause like @colpat) set @include = 1 else if exists (select * from sysmergesubsetfilters where art_nickname = @tablenick and join_filterclause like @colpat) set @include = 1 else if exists (select * from sysmergesubsetfilters where join_nickname = @tablenick and join_filterclause like @colpat) set @include = 1 -- If we want this column, map its type and insert a row to temp table if @include <> 1 begin goto fetchnext end if @typename='nvarchar' or @typename='nchar' -- a unit of nchar takes 2 bytes set @len = @len/2 exec @retcode = dbo.sp_MSmaptype @typename out, @len, @prec, @scale if @@ERROR<>0 or @retcode<>0 goto errlabel set @colname = QUOTENAME(@colname) -- Always make columns nullable when we add them because we might have -- existing rows in the before image table. set @command = 'alter table ' + @biname + ' ADD ' + @colname + ' ' + @typename + ' NULL ' exec (@command) if @@error <> 0 goto errlabel -- Create an index set @colidstr =convert(nvarchar(3), @colid) set @command = 'create index ' + @biname + '_' + @colidstr + ' on ' + @biname + ' (' + @colname + ')' exec (@command) if @@error <> 0 goto errlabel fetchnext: /* Repeat the loop with next column */ fetch next from col_cursor into @colname, @status, @typename, @len, @prec, @scale, @isnullable, @colid end close col_cursor deallocate col_cursor return 0 errlabel: close col_cursor deallocate col_cursor return 1 go -------------------------------------------------------------------------------- --. sp_MSgetbeforetableinsert -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSgetbeforetableinsert') drop procedure sp_MSgetbeforetableinsert go raiserror('Creating procedure sp_MSgetbeforetableinsert', 0,1) go create procedure sp_MSgetbeforetableinsert @objid int, @inscommand nvarchar(2000) output AS declare @before_objid int declare @before_name sysname declare @collist nvarchar(1000) declare @colname sysname -- Do we have a before table? select @before_objid = max(before_image_objid) from sysmergearticles where objid = @objid and before_image_objid is not null select @before_name = OBJECT_NAME(@before_objid) if @before_name is null begin set @inscommand = '' return 0 end set @collist = '' -- Loop over columns to make the column list for the insert / select command declare col_cursor CURSOR LOCAL FAST_FORWARD for select name from syscolumns where id = @before_objid and name <> 'generation' order by colid FOR READ ONLY open col_cursor fetch next from col_cursor into @colname while (@@fetch_status <> -1) begin set @collist = @collist + QUOTENAME(@colname) + ', ' fetch next from col_cursor into @colname end close col_cursor deallocate col_cursor -- Our list has all of the columns except generation since that gets set to a local variable -- Make the insert command set @inscommand = 'insert into ' + QUOTENAME(@before_name) + ' ( ' + @collist + ' generation) select ' + @collist + ' @newgen from deleted' return 0 go -------------------------------------------------------------------------------- --. sp_MSfixlineagemismatch -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSfixlineagemismatch') drop procedure sp_MSfixlineagemismatch raiserror('Creating procedure sp_MSfixlineagemismatch', 0,1) go create procedure sp_MSfixlineagemismatch as if exists (select * from sysobjects where type = 'U' and name = 'MSmerge_contents') begin update MSmerge_contents set lineage = substring(lineage, 1, 4) + substring(lineage, 13, 4) + substring(lineage, 9, 240) where substring(lineage, 13, 1) > substring(lineage, 5, 1) and substring(lineage, 14, 3) = substring(lineage, 6, 3) or substring(lineage, 14, 1) > substring(lineage, 6, 1) and substring(lineage, 15, 2) = substring(lineage, 7, 2) or substring(lineage, 15, 1) > substring(lineage, 7, 1) and substring(lineage, 16, 1) = substring(lineage, 8, 1) or substring(lineage, 16, 1) > substring(lineage, 8, 1) end go exec dbo.sp_MS_marksystemobject sp_MSfixlineagemismatch go grant exec on dbo.sp_MSfixlineagemismatch to public go -------------------------------------------------------------------------------- --. sp_MSinsertgenerationschemachanges -------------------------------------------------------------------------------- if exists (select * from sysobjects where type = 'P' and name = 'sp_MSinsertgenerationschemachanges') drop procedure sp_MSinsertgenerationschemachanges go create procedure sp_MSinsertgenerationschemachanges @publication sysname AS declare @mingen int declare @lastrecgen int declare @lastrecguid uniqueidentifier declare @lastsentgen int declare @lastsentguid uniqueidentifier declare @db_name sysname declare @repid uniqueidentifier declare @pubid uniqueidentifier declare @schemaversion int declare @schemaguid uniqueidentifier declare @schematype int declare @schematext nvarchar(2000) declare @artid uniqueidentifier declare @retcode int set nocount on set @lastrecgen = NULL set @lastsentgen = NULL begin tran save TRAN MSinsertgenerationschemachanges set @db_name = db_name() select @pubid = pubid from sysmergepublications where name = @publication and publisher = @@SERVERNAME and publisher_db = @db_name if @pubid IS NULL BEGIN RAISERROR (20026, 16, -1, @publication) RETURN (1) END SELECT @repid = subid FROM sysmergesubscriptions where pubid = @pubid and subid = @pubid if @repid is NULL begin RAISERROR(20021, 16, -1) return (1) end select @mingen = min(generation) from MSmerge_genhistory where guidlocal = '00000000-0000-0000-0000-000000000000' if @mingen IS NOT NULL select @lastrecgen = max(generation) from MSmerge_genhistory where generation < @mingen if @lastrecgen IS NOT NULL begin select @lastrecguid = guidsrc from MSmerge_genhistory where generation = @lastrecgen set @artid = NULL set @schematype = 5 /* last rec gen schema type */ select @schematext = 'exec dbo.sp_MSsetlastrecgen ' + '''' + convert(nchar(36), @repid) + '''' + ',' + '''' + convert(nvarchar(10), @lastrecgen) + '''' + ',' + '''' + convert(nchar(36), @lastrecguid) + '''' if exists (select * from sysmergeschemachange where pubid = @pubid AND schematype = @schematype) begin /* Select the existing schema guid */ select @schemaversion = schemaversion, @schemaguid = schemaguid from sysmergeschemachange where pubid = @pubid AND schematype = @schematype /* ** Update the schema change version */ exec @retcode = dbo.sp_MSupdateschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext if @@error <> 0 or @retcode <> 0 goto FAILURE 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 goto FAILURE end end select @lastsentgen = max(generation) 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 pubid = @pubid)) if @lastsentgen IS NOT NULL begin select @lastsentguid = guidsrc from MSmerge_genhistory where generation = @lastsentgen set @artid = NULL set @schematype = 6 /* last sent gen schema type */ select @schematext = 'exec dbo.sp_MSsetlastsentgen ' + '''' + convert(nchar(36), @repid) + '''' + ',' + '''' + convert(nvarchar(10), @lastsentgen) + '''' + ',' + '''' + convert(nchar(36), @lastsentguid) + '''' if exists (select * from sysmergeschemachange where pubid = @pubid AND schematype = @schematype) begin /* Select the existing schema guid */ select @schemaversion = schemaversion, @schemaguid = schemaguid from sysmergeschemachange where pubid = @pubid AND schematype = @schematype /* ** Update the schema change version */ exec @retcode = dbo.sp_MSupdateschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext if @@error <> 0 or @retcode <> 0 goto FAILURE 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 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 MSinsertgenerationschemachanges COMMIT TRANSACTION end RETURN 1 go exec dbo.sp_MS_marksystemobject sp_MSinsertgenerationschemachanges go grant exec on dbo.sp_MSinsertgenerationschemachanges to public go -------------------------------------------------------------------------------- -- END OF FILE: Turn off marking of system objects. -- DO NOT ADD ANYTHING AFTER THIS POINT -------------------------------------------------------------------------------- exec sp_MS_upd_sysobj_category 2 go exec sp_configure 'allow updates',0 go reconfigure with override go