/* ** replsys.sql 1997/02/12 22:03 ** ** ** Copyright Microsoft, Inc. 1998, 1999 ** All Rights Reserved. ** Use, duplication, or disclosure by the United States Government ** is subject to restrictions as set forth in subdivision (c) (1) (ii) ** of the Rights in Technical Data and Computer Software clause ** at CFR 252.227-7013. Microsoft, Inc. One Microsoft Way, Redmond WA ** 98052. SQL Server 7.0 */ dump tran master with no_log go exec dbo.sp_configure 'update',1 go reconfigure with override go set ANSI_NULLS off go use master go exec dbo.sp_MS_upd_sysobj_category 1 --Capture time for use at the end go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreplcheck_name') drop procedure sp_MSreplcheck_name go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreplcheck_publish') drop procedure sp_MSreplcheck_publish go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSsetaccesslist') drop procedure sp_MSsetaccesslist go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MScheck_subscription') drop procedure sp_MScheck_subscription go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSenumcolumns') drop procedure sp_MSenumcolumns go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSlocktable') drop procedure sp_MSlocktable go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreplcheck_connection') drop procedure sp_MSreplcheck_connection go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreplcheck_pull') drop procedure sp_MSreplcheck_pull go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreplcheck_qv') drop procedure sp_MSreplcheck_qv go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSpublicationcleanup') drop procedure sp_MSpublicationcleanup if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSaddanonymousreplica') drop procedure sp_MSaddanonymousreplica if exists (select * from sysobjects where type = 'P' and name = 'sp_reinitmergepullsubscription') drop procedure sp_reinitmergepullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_expired_subscription_cleanup') drop procedure sp_expired_subscription_cleanup if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSarticlecleanup') drop procedure sp_MSarticlecleanup if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSdroparticleprocs') drop procedure sp_MSdroparticleprocs if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSdroparticletriggers') drop procedure sp_MSdroparticletriggers if exists (select * from sysobjects where type = 'P ' and name = 'sp_MScheckvalidsystables') drop procedure sp_MScheckvalidsystables if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreplcheck_subscribe') drop procedure sp_MSreplcheck_subscribe go if exists (select * from sysobjects where type = 'P ' and name = 'sp_replicationoption') drop procedure sp_replicationoption go if exists (select * from sysobjects where type = 'P ' and name = 'sp_helpreplicationoption') drop procedure sp_helpreplicationoption go if exists (select * from sysobjects where type in ('P ') and name = 'sp_MSmergesubscribedb') drop procedure sp_MSmergesubscribedb if exists (select * from sysobjects where type in ('P ') and name = 'sp_MSremovedbreplication') drop procedure sp_MSremovedbreplication if exists (select * from sysobjects where type = 'P ' and name = 'sp_addpullsubscription') drop procedure sp_addpullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_reinitpullsubscription') drop procedure sp_reinitpullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_addmergepullsubscription') drop procedure sp_addmergepullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_dropmergepullsubscription') drop procedure sp_dropmergepullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_changemergepullsubscription') drop procedure sp_changemergepullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_helpmergepullsubscription') drop procedure sp_helpmergepullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSchange_priority') drop procedure sp_MSchange_priority if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSdrop_mergesystables') drop procedure sp_MSdrop_mergesystables if exists (select * from sysobjects where type = 'P ' and name = 'sp_MScreate_mergesystables') drop procedure sp_MScreate_mergesystables if exists (select * from sysobjects where type = 'P ' and name = 'sp_addpullsubscription_agent') drop procedure sp_addpullsubscription_agent if exists (select * from sysobjects where type = 'P ' and name = 'sp_helpsubscription_properties') drop procedure sp_helpsubscription_properties if exists (select * from sysobjects where type = 'P ' and name = 'sp_change_subscription_properties') drop procedure sp_change_subscription_properties if exists (select * from sysobjects where type = 'P' and name = 'sp_MSget_pullsubsagent_owner') drop procedure sp_MSget_pullsubsagent_owner if exists (select * from sysobjects where type = 'P' and name = 'sp_MSget_mergepullsubsagent_owner') drop procedure sp_MSget_mergepullsubsagent_owner if exists (select * from sysobjects where type = 'P ' and name = 'sp_addmergepullsubscription_agent') drop procedure sp_addmergepullsubscription_agent if exists (select * from sysobjects where type = 'P ' and name = 'sp_droppullsubscription') drop procedure sp_droppullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_vupgrade_publisherdb') drop procedure sp_vupgrade_publisherdb if exists (select * from sysobjects where type = 'P ' and name = 'sp_vupgrade_publisher') drop procedure sp_vupgrade_publisher if exists (select * from sysobjects where type = 'P ' and name = 'sp_helppullsubscription') drop procedure sp_helppullsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSunmarkreplinfo') drop procedure sp_MSunmarkreplinfo if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSunmarkifneeded') drop procedure sp_MSunmarkifneeded if exists (select * from sysobjects where type = 'P ' and name = 'sp_MStable_has_unique_index') drop procedure sp_MStable_has_unique_index if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreplraiserror') drop procedure sp_MSreplraiserror if exists (select * from sysobjects where type = 'P ' and name = 'sp_check_sync_trigger') drop procedure sp_check_sync_trigger if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreplicationcompatlevel') drop proc sp_MSreplicationcompatlevel if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSgenreplnickname') drop proc sp_MSgenreplnickname if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSenumallpublications') drop proc sp_MSenumallpublications if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSenumtranpublications') drop proc sp_MSenumtranpublications if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSenummergepublications') drop proc sp_MSenummergepublications if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSenum3rdpartypublications') drop proc sp_MSenum3rdpartypublications if exists (select * from sysobjects where type = 'P' and name = 'sp_MSgetreplicainfo') drop procedure sp_MSgetreplicainfo if exists (select * from sysobjects where type = 'P ' and name = 'sp_subscription_cleanup') drop procedure sp_subscription_cleanup if exists (select * from sysobjects where type = 'P ' and name = 'sp_mergesubscription_cleanup') drop procedure sp_mergesubscription_cleanup if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSpad_command') drop procedure sp_MSpad_command if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSflush_command') drop procedure sp_MSflush_command if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSget_colinfo') drop procedure sp_MSget_colinfo if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSget_type') drop procedure sp_MSget_type if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSget_col_position') drop procedure sp_MSget_col_position if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_where_clause') drop procedure sp_MSscript_where_clause if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_params') drop procedure sp_MSscript_params if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_begintrig1') drop procedure sp_MSscript_begintrig1 if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_begintrig2') drop procedure sp_MSscript_begintrig2 if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_endtrig') drop procedure sp_MSscript_endtrig if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_trigger_variables') drop procedure sp_MSscript_trigger_variables if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_trigger_assignment') drop procedure sp_MSscript_trigger_assignment if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_trigger_fetch_statement') drop procedure sp_MSscript_trigger_fetch_statement if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_trigger_exec_rpc') drop procedure sp_MSscript_trigger_exec_rpc if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_trigger_update_checks') drop procedure sp_MSscript_trigger_update_checks if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_trigger_updates') drop procedure sp_MSscript_trigger_updates if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_singlerow_trigger') drop procedure sp_MSscript_singlerow_trigger if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_multirow_trigger') drop procedure sp_MSscript_multirow_trigger if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_sync_ins_trig') drop procedure sp_MSscript_sync_ins_trig if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_sync_upd_trig') drop procedure sp_MSscript_sync_upd_trig if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_sync_del_trig') drop procedure sp_MSscript_sync_del_trig if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSget_synctran_column') drop procedure sp_MSget_synctran_column if exists (select * from sysobjects where type = 'P ' and name = 'sp_check_for_sync_trigger') drop procedure sp_check_for_sync_trigger if exists (select * from sysobjects where type = 'P ' and name = 'sp_addsynctriggers') drop procedure sp_addsynctriggers if exists (select * from sysobjects where type = 'P ' and name = 'sp_helpreplicationdboption') drop procedure sp_helpreplicationdboption if exists (select * from sysobjects where type = 'P' and name = 'sp_MSgetreplnick') drop procedure sp_MSgetreplnick if exists (select * from sysobjects where type = 'P' and name = 'sp_MStestbit') drop procedure sp_MStestbit if exists (select * from sysobjects where type = 'P' and name = 'sp_MSsetbit') drop procedure sp_MSsetbit if exists (select * from sysobjects where type = 'P' and name = 'sp_MSinsertcontents') drop procedure sp_MSinsertcontents if exists (select * from sysobjects where type = 'P' and name = 'sp_MSupdatecontents') drop procedure sp_MSupdatecontents if exists (select * from sysobjects where type = 'P' and name = 'sp_MSdeletecontents') drop procedure sp_MSdeletecontents if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSadd_repl_job') drop procedure sp_MSadd_repl_job IF EXISTS (select * from sysobjects where name = 'sp_MScheck_agent_instance' and type = 'P') DROP PROCEDURE sp_MScheck_agent_instance if exists (select * from sysobjects where name = 'xp_mergexpusage') execute dbo.sp_dropextendedproc 'xp_mergexpusage' if exists (select * from sysobjects where name = 'sp_get_distributor' and type = 'P') drop procedure sp_get_distributor if exists (select * from sysobjects where name = 'sp_MSrepl_addrolemember' and type = 'P') drop procedure sp_MSrepl_addrolemember if exists (select * from sysobjects where name = 'sp_MSrepl_droprolemember' and type = 'P') drop procedure sp_MSrepl_droprolemember if exists (select * from sysobjects where name = 'sp_table_validation' and type = 'P') drop procedure sp_table_validation if exists (select * from sysobjects where name = 'sp_MScreate_sub_tables' and type = 'P') drop procedure sp_MScreate_sub_tables go if exists (select * from sysobjects where name = 'sp_removedbreplication' and type = 'P') drop procedure sp_removedbreplication if exists (select * from sysobjects where name = 'sp_removesrvreplication' and type = 'P') drop procedure sp_removesrvreplication if exists (select * from sysobjects where name = 'sp_vupgrade_subscription_databases' and type = 'P') drop procedure sp_vupgrade_subscription_databases if exists (select * from sysobjects where name = 'sp_vupgrade_MSsubscription_properties' and type = 'P') drop procedure sp_vupgrade_MSsubscription_properties if exists (select * from sysobjects where name = 'sp_vupgrade_mergetables' and type = 'P') drop procedure sp_vupgrade_mergetables if exists (select * from sysobjects where name = 'sp_vupgrade_replication' and type = 'P') drop procedure sp_vupgrade_replication if exists (select * from sysobjects where name = 'sp_vupgrade_replmsdb' and type = 'P') drop procedure sp_vupgrade_replmsdb if exists (select * from sysobjects where name = 'sp_restoredbreplication' and type = 'P') drop procedure sp_restoredbreplication if exists (select * from sysobjects where name = 'sp_MSget_publisher_rpc' and type = 'P') drop procedure sp_MSget_publisher_rpc if exists (select * from sysobjects where name = 'sp_link_publication' and type = 'P') drop procedure sp_link_publication if exists (select * from sysobjects where name = 'sp_MS_replication_installed' and type = 'P') drop procedure sp_MS_replication_installed if exists (select * from sysobjects where name = 'sp_MSunc_to_drive' and type = 'P') drop procedure sp_MSunc_to_drive if exists (select * from sysobjects where name = 'sp_MSdrop_object' and type = 'P') drop procedure sp_MSdrop_object if exists (select * from sysobjects where name = 'sp_MSregistersubscription' and type = 'P') drop procedure sp_MSregistersubscription if exists (select * from sysobjects where name = 'sp_MSunregistersubscription' and type = 'P') drop procedure sp_MSunregistersubscription if exists (select * from sysobjects where name = 'sp_MSrepl_linkedservers_rowset' and type = 'P') drop procedure sp_MSrepl_linkedservers_rowset if exists (select * from sysobjects where name = 'sp_MSrepl_isdbowner' and type = 'P') drop procedure sp_MSrepl_isdbowner if exists (select * from sysobjects where name = 'sp_MSget_qualified_name' and type = 'P') drop procedure sp_MSget_qualified_name if exists (select * from sysobjects where name = 'sp_MSscript_pkvar_assignment' and type = 'P') drop procedure sp_MSscript_pkvar_assignment go if exists (select * from sysobjects where name = 'sp_MSget_jobstate' and type = 'P') drop procedure sp_MSget_jobstate go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSget_publication_from_taskname') drop procedure sp_MSget_publication_from_taskname go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSrepl_check_server') drop procedure sp_MSrepl_check_server go if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSreset_synctran_bit') drop procedure sp_MSreset_synctran_bit go sp_addextendedproc 'xp_mergexpusage', 'xprepl.dll' go grant exec on xp_mergexpusage to public go if exists (select * from sysobjects where name = 'xp_showlineage') execute dbo.sp_dropextendedproc 'xp_showlineage' go sp_addextendedproc 'xp_showlineage', 'xprepl.dll' go grant exec on xp_showlineage to public go if exists (select * from sysobjects where name = 'xp_updatelineage') execute dbo.sp_dropextendedproc 'xp_updatelineage' go sp_addextendedproc 'xp_updatelineage', 'xprepl.dll' go grant exec on xp_updatelineage to public go if exists (select * from sysobjects where name = 'xp_proxiedmetadata') execute dbo.sp_dropextendedproc 'xp_proxiedmetadata' go sp_addextendedproc 'xp_proxiedmetadata', 'xprepl.dll' go grant exec on xp_proxiedmetadata to public go if exists (select * from sysobjects where name = 'xp_initcolvs') execute dbo.sp_dropextendedproc 'xp_initcolvs' go sp_addextendedproc 'xp_initcolvs', 'xprepl.dll' go grant exec on xp_initcolvs to public go if exists (select * from sysobjects where name = 'xp_updatecolvbm') execute dbo.sp_dropextendedproc 'xp_updatecolvbm' go sp_addextendedproc 'xp_updatecolvbm', 'xprepl.dll' go grant exec on xp_updatecolvbm to public go if exists (select * from sysobjects where name = 'xp_showcolv') execute dbo.sp_dropextendedproc 'xp_showcolv' go sp_addextendedproc 'xp_showcolv', 'xprepl.dll' go grant exec on xp_showcolv to public go if exists (select * from sysobjects where name = 'xp_execresultset') execute dbo.sp_dropextendedproc 'xp_execresultset' go sp_addextendedproc 'xp_execresultset', 'xprepl.dll' go grant exec on xp_execresultset to public go if exists (select * from sysobjects where name = 'xp_varbintohexstr') execute dbo.sp_dropextendedproc 'xp_varbintohexstr' go sp_addextendedproc 'xp_varbintohexstr', 'xprepl.dll' go grant exec on xp_varbintohexstr to public go if exists (select * from sysobjects where name = 'xp_intersectbitmaps') execute dbo.sp_dropextendedproc 'xp_intersectbitmaps' go sp_addextendedproc 'xp_intersectbitmaps', 'xprepl.dll' go grant exec on xp_intersectbitmaps to public go if exists (select * from sysobjects where name = 'xp_displayparamstmt') execute dbo.sp_dropextendedproc 'xp_displayparamstmt' go sp_addextendedproc 'xp_displayparamstmt', 'xprepl.dll' go grant exec on xp_displayparamstmt to public go if exists (select * from sysobjects where name = 'xp_printstatements') execute dbo.sp_dropextendedproc 'xp_printstatements' go sp_addextendedproc 'xp_printstatements', 'xprepl.dll' go grant exec on xp_printstatements to public go /* Create table dbo.MSreplication_options */ IF NOT EXISTS (SELECT * FROM sysobjects WHERE name = 'MSreplication_options' and type = 'U') BEGIN raiserror('Creating procedure Creating table MSreplication_options',0,1) CREATE TABLE dbo.MSreplication_options ( optname sysname NOT NULL, value bit NOT NULL, major_version int NOT NULL, minor_version int NOT NULL, revision int NOT NULL, install_failures int NOT NULL ) END GO IF NOT EXISTS (SELECT * FROM MSreplication_options WHERE optname = 'transactional') INSERT INTO MSreplication_options VALUES ('transactional',0,0,0,0,0) IF NOT EXISTS (SELECT * FROM MSreplication_options WHERE optname = 'merge') INSERT INTO MSreplication_options VALUES ('merge',0,0,0,0,0) 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 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 exec dbo.sp_MS_marksystemobject sp_MSreplcheck_name go raiserror('Creating procedure sp_MScheckvalidsystables', 0,1) GO create procedure sp_MScheckvalidsystables @validsubs int output AS if not exists (select name from sysobjects where name='sysmergesubscriptions') begin set @validsubs = 0 return end /* Is there a valid non-loopback subscription? */ if exists (select * from sysmergesubscriptions where db_name=db_name() and srvid = (select srvid from master..sysservers where UPPER(srvname) = UPPER(@@servername)) and subid <> partnerid) begin set @validsubs = 1 return end /* Only possible subscriptions are loopbacks. If database not enabled for publishing, ** then they don't indicate a valid publication/subscription. */ if not exists (select name from master..sysdatabases where (category & 4) = 4 and name = db_name()) begin set @validsubs = 0 return end /* Database has merge publishing turned on, is probably a publisher. Look for loopback ** subscription just to be sure... */ if exists (select * from sysmergesubscriptions where db_name=db_name() and srvid = (select srvid from master..sysservers where UPPER(srvname) = UPPER(@@servername))) begin set @validsubs = 1 return end /* Must not be valid... */ set @validsubs = 0 return GO raiserror('Creating procedure sp_MSdrop_mergesystables', 0,1) GO create procedure sp_MSdrop_mergesystables as begin tran save transaction drop_mergesystables if exists (select * from sysobjects where name = 'sysmergearticles') begin drop table sysmergearticles end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'sysmergepublications') begin drop table sysmergepublications end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'sysmergesubscriptions') begin drop table sysmergesubscriptions end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'MSmerge_contents') begin drop table MSmerge_contents end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'MSmerge_replinfo') begin drop table MSmerge_replinfo end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'MSmerge_tombstone') begin drop table MSmerge_tombstone end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'MSmerge_genhistory') begin drop table MSmerge_genhistory end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'MSmerge_delete_conflicts') begin drop table MSmerge_delete_conflicts end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'sysmergeschemachange') begin drop table sysmergeschemachange end if @@error<>0 goto Error if exists (select * from sysobjects where name = 'sysmergesubsetfilters') begin drop table sysmergesubsetfilters end if @@error<>0 goto Error commit transaction return 0 Error: RAISERROR (20007, 16, -1) if @@trancount > 0 begin ROLLBACK TRANSACTION drop_mergesystables COMMIT TRANSACTION end return 1 go exec dbo.sp_MS_marksystemobject sp_MSdrop_mergesystables go raiserror ('Executing procedure dbo.sp_MSdrop_mergesystables.',0,1) go exec dbo.sp_MSdrop_mergesystables go dump tran master with no_log 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 ) if @@ERROR <> 0 goto Error 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 ) 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 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 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 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 clustered index schemachangeversion on sysmergeschemachange(schemaversion) 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 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 exec dbo.sp_MS_marksystemobject sp_MScreate_mergesystables go raiserror('Creating procedure sp_MStestbit',0,1) go create procedure sp_MStestbit @bm varbinary(125), @coltotest smallint AS declare @word smallint declare @bit smallint declare @mask binary(2) declare @mval int declare @oldword binary(2) if @coltotest < 1 return 0 SELECT @word = CONVERT(smallint, 1 + FLOOR((@coltotest -1)/16)) SELECT @bit = (@coltotest -1) % 16 SELECT @mval = POWER(2, @bit) SELECT @mask = convert( binary(2), unicode( substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) ) ) SELECT @oldword = convert( binary(2), SUBSTRING( convert( nvarchar(63),@bm), @word, 1) ) IF @oldword IS NULL return 0 return convert( smallint, @oldword ) & convert( smallint, @mask ) go exec dbo.sp_MS_marksystemobject sp_MStestbit go raiserror('Creating procedure sp_MSsetbit',0,1) go create procedure sp_MSsetbit @bm varbinary(125) output, @coltoadd smallint AS declare @word smallint declare @bit smallint declare @mask binary(2) declare @mval int declare @newword binary(2) declare @oldword binary(2) SELECT @word = CONVERT(smallint, 1 + FLOOR((@coltoadd-1)/16)) IF @word > 62 return 0 SELECT @bit = (@coltoadd-1) % 16 SET @mval = POWER(2, @bit) SELECT @mask = convert( binary(2), unicode( substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) ) ) if @bm is null set @bm = 0x0 while datalength(@bm) < @word * 2 set @bm = @bm + 0x0000 SET @oldword = convert( binary(2), SUBSTRING( convert(nvarchar(63),@bm), @word, 1) ) IF @oldword IS NULL SET @oldword = 0x00 SET @newword = convert( smallint, @oldword) | convert( smallint, @mask ) SET @bm = CONVERT(varbinary(125), STUFF( CONVERT(nvarchar(63),@bm), @word, 1, convert( nchar(1),@newword)) ) go exec dbo.sp_MS_marksystemobject sp_MSsetbit go raiserror('Creating procedure sp_MSinsertcontents',0,1) go create procedure sp_MSinsertcontents @tablenick int, @rowguid uniqueidentifier, @lineage varbinary(249), @colv1 varbinary(2048) AS /* ** permission check */ declare @retcode int declare @objid int declare @owner sysname declare @artid uniqueidentifier declare @guidstr nvarchar(32) declare @instrigger sysname select @objid = objid, @artid=artid from sysmergearticles where nickname=@tablenick select @owner =user_name(uid) from sysobjects where id=@objid exec @retcode=sp_MSguidtostr @artid, @guidstr out if @retcode<>0 or @@ERROR<>0 return (1) set @instrigger = @owner + '.ins_' + @guidstr if trigger_nestlevel(object_id(@instrigger)) = 0 begin raiserror(14126, 16, -1) return (1) -- current user does not have insert permission to underlying table end insert into MSmerge_contents (tablenick, rowguid, generation, partchangegen, joinchangegen, lineage, colv1) values (@tablenick, @rowguid, 0, 0, 0, @lineage, @colv1) if @@error <> 0 begin raiserror (20041, 16, -1) return (1) end delete from MSmerge_tombstone where rowguid = @rowguid and tablenick = @tablenick if @@error <> 0 begin raiserror (20041, 16, -1) return (1) end go exec dbo.sp_MS_marksystemobject sp_MSinsertcontents go grant exec on dbo.sp_MSinsertcontents to public raiserror('Creating procedure sp_MSupdatecontents',0,1) go create procedure sp_MSupdatecontents @tablenick int, @rowguid uniqueidentifier, @lineage varbinary(249), @colv1 varbinary(2048), @partchange int = null, @joinchange int = null AS /* ** permission check */ declare @retcode int declare @objid int declare @owner sysname declare @artid uniqueidentifier declare @guidstr nvarchar(32) declare @updtrigger sysname select @objid = objid, @artid=artid from sysmergearticles where nickname=@tablenick select @owner =user_name(uid) from sysobjects where id=@objid exec @retcode=sp_MSguidtostr @artid, @guidstr out if @retcode<>0 or @@ERROR<>0 return (1) set @updtrigger = @owner + '.upd_' + @guidstr if trigger_nestlevel(object_id(@updtrigger)) = 0 begin raiserror(14126, 16, -1) return (1) -- current user does not 'update all' permission upon underlying table end update MSmerge_contents set lineage = @lineage, generation = 0, colv1 = @colv1 where tablenick = @tablenick and rowguid = @rowguid if (@@rowcount = 0) insert into MSmerge_contents (tablenick, rowguid, generation, joinchangegen, lineage, colv1) values (@tablenick, @rowguid, 0, 1, @lineage, @colv1) if @@error <> 0 begin raiserror (20041, 16, -1) return (1) end if @partchange = 1 begin update MSmerge_contents set partchangegen = 0, joinchangegen = 0 where tablenick = @tablenick and rowguid = @rowguid if @@error <> 0 begin raiserror (20041, 16, -1) return (1) end end else if @joinchange = 1 begin update MSmerge_contents set joinchangegen = 0 where tablenick = @tablenick and rowguid = @rowguid if @@error <> 0 begin raiserror (20041, 16, -1) return (1) end end go exec dbo.sp_MS_marksystemobject sp_MSupdatecontents go grant exec on dbo.sp_MSupdatecontents to public raiserror(15339, -1, -1, 'sp_MSdeletecontents') go create procedure sp_MSdeletecontents @tablenick int, @rowguid uniqueidentifier AS declare @nick int declare @reason nvarchar(255) declare @lineage varbinary(255) /* ** permission check */ declare @retcode int declare @objid int declare @owner sysname declare @artid uniqueidentifier declare @guidstr nvarchar(32) declare @deltrigger sysname select @objid = objid, @artid=artid from sysmergearticles where nickname=@tablenick select @owner =user_name(uid) from sysobjects where id=@objid exec @retcode=sp_MSguidtostr @artid, @guidstr out if @retcode<>0 or @@ERROR<>0 return (1) set @deltrigger = @owner + '.del_' + @guidstr if trigger_nestlevel(object_id(@deltrigger)) = 0 begin raiserror(14126, 16, -1) return (1) -- current user does not have 'delete' permission to underlying table end exec dbo.sp_MSgetreplnick @nickname = @nick out if (@@error <> 0) or @nick IS NULL begin RAISERROR (14055, 11, -1) RETURN(1) end select @lineage = lineage from MSmerge_contents (UPDLOCK ROWLOCK index = 1) where tablenick = @tablenick and rowguid = @rowguid exec master..xp_updatelineage @lineage output, @nick select @reason = 'user delete' insert into MSmerge_tombstone (rowguid, tablenick, type, lineage, generation, reason) values (@rowguid, @tablenick, 1, @lineage, 0, @reason) if @@error <> 0 begin raiserror (20041, 16, -1) return (1) end delete from MSmerge_contents where tablenick = @tablenick and rowguid = @rowguid if @@error <> 0 begin raiserror (20041, 16, -1) return (1) end go exec dbo.sp_MS_marksystemobject sp_MSdeletecontents go grant exec on dbo.sp_MSdeletecontents to public raiserror('Creating procedure sp_MSunmarkifneeded',0,1) GO CREATE PROCEDURE sp_MSunmarkifneeded( @object sysname, @pubid uniqueidentifier )AS declare @table_in_use int declare @retcode int select @table_in_use = 0 if EXISTS (select * from sysmergearticles where pubid<>@pubid and objid=object_id(@object)) 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 exec dbo.sp_MS_marksystemobject sp_MSunmarkifneeded go grant exec on dbo.sp_MSunmarkifneeded to public go raiserror('Creating procedure sp_MSunmarkreplinfo',0,1) GO CREATE PROCEDURE sp_MSunmarkreplinfo( @object sysname, /* Name of the table, unqualitied */ @owner sysname = NULL, /* Name of the owner, unqualified */ @type smallint = 0 /* default is to unmark, as name implies */ )AS declare @merge_pub_object_bit int declare @merge_pub_unmark_bit int declare @id int declare @qualified_name nvarchar(258) if @owner is NULL or @owner='' select @owner = user_name(uid) from sysobjects where id = object_id(QUOTENAME(@object)) select @qualified_name = QUOTENAME(@owner) + '.' + QUOTENAME(@object) select @id = object_id(@qualified_name) select @merge_pub_object_bit = 128 select @merge_pub_unmark_bit = ~@merge_pub_object_bit if exists (select name from sysobjects where id = @id) begin if @type = 0 /* type = 0, unmark; else mark the bit */ begin BEGIN TRANSACTION exec dbo.sp_replupdateschema @qualified_name update sysobjects set replinfo = replinfo & @merge_pub_unmark_bit where id = @id COMMIT TRANSACTION end else begin BEGIN TRANSACTION exec dbo.sp_replupdateschema @qualified_name update sysobjects set replinfo = replinfo | @merge_pub_object_bit where id = @id COMMIT TRANSACTION end end GO exec dbo.sp_MS_marksystemobject sp_MSunmarkreplinfo go grant execute on dbo.sp_MSunmarkreplinfo to public raiserror('Creating procedure sp_MSaddanonymousreplica',0,1) GO CREATE PROCEDURE sp_MSaddanonymousreplica (@publication sysname, @publisher sysname, @publisherDB sysname, @anonymous int ) as declare @retcode int declare @subscription_type nvarchar(15) if exists (select * from sysobjects where name='sysmergepublications') begin IF EXISTS (select name from sysmergepublications where name=@publication and UPPER(publisher)=UPPER(@publisher) and publisher_db = @publisherDB) return (0) -- replica exists. -- else call this SP to add this replica end if @anonymous = 1 select @subscription_type = 'anonymous' else select @subscription_type = 'local' exec @retcode = dbo.sp_addmergepullsubscription @publication = @publication, @publisher = @publisher, @publisher_db=@publisherDB, @subscriber_type =@subscription_type IF @retcode<>0 or @@ERROR<>0 return (1) return (0) GO exec dbo.sp_MS_marksystemobject sp_MSaddanonymousreplica go grant execute on dbo.sp_MSaddanonymousreplica to public go raiserror('Creating procedure sp_MSgetreplicainfo',0,1) GO CREATE PROCEDURE sp_MSgetreplicainfo (@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 */ as declare @srvid int declare @retcode int declare @repid uniqueidentifier declare @pubid uniqueidentifier declare @schemaguid uniqueidentifier declare @nickname int declare @subscription_type int declare @reptype tinyint declare @priority real declare @schversion int declare @status int declare @partnerid uniqueidentifier declare @sync_type tinyint declare @description nvarchar(255) /* ** 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 BEGIN RAISERROR (14080, 16, -1) RETURN (1) END IF @srvid IS NULL BEGIN RAISERROR (14010, 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, 16, -1, @publication) return (1) end if (@datasource_type = 0) begin SELECT @repid = subid, @priority = priority, @reptype = subscriber_type, @subscription_type = subscription_type , @status = status, @partnerid = partnerid, @sync_type = sync_type, @description = description FROM sysmergesubscriptions WHERE srvid = @srvid and db_name = @db_name and pubid = @pubid END ELSE BEGIN SELECT @repid = subid, @priority = priority, @reptype = subscriber_type, @subscription_type = subscription_type , @status = status, @partnerid = partnerid, @sync_type = sync_type, @description = description FROM sysmergesubscriptions WHERE srvid = @srvid and pubid = @pubid END if @repid is NULL begin RAISERROR(20021, 16, -1) return (1) end select @schversion = schemaversion, @schemaguid = schemaguid from MSmerge_replinfo where repid = @repid select @nickname = replnickname from MSmerge_replinfo where repid = @repid select @repid, @nickname, @reptype, @subscription_type, @priority, @schversion, @schemaguid, @status, @partnerid, @sync_type, @description return (0) go exec dbo.sp_MS_marksystemobject sp_MSgetreplicainfo go grant execute on dbo.sp_MSgetreplicainfo to public raiserror('Creating procedure sp_MSadd_repl_job',0,1) go CREATE PROCEDURE sp_MSadd_repl_job @name nvarchar(200), @subsystem nvarchar(60) = 'TSQL', @server sysname = NULL, @username sysname = NULL, @databasename sysname = NULL, @enabled TINYINT = 0, @freqtype INT = 2, -- 2 means OnDemand @freqinterval INT = 1, @freqsubtype INT = 1, @freqsubinterval INT = 1, @freqrelativeinterval INT = 1, @freqrecurrencefactor INT = 1, @activestartdate INT = 0, @activeenddate INT = 0, @activestarttimeofday INT = 0, @activeendtimeofday INT = 0, @nextrundate INT = 0, @nextruntime INT = 0, @runpriority INT = 0, @emailoperatorname nvarchar(100) = NULL, @retryattempts INT = NULL, @retrydelay INT = 0, @command nvarchar(4000)= NULL, @loghistcompletionlevel INT = 2, @emailcompletionlevel INT = 0, @description nvarchar(255) = NULL, @tagadditionalinfo nvarchar(96) = NULL, @tagobjectid INT = NULL, @tagobjecttype INT = NULL, @cmdexecsuccesscode INT = 0, @category_name sysname = NULL, -- New for 7.0 @failure_detection BIT = 0, @agent_id INT = NULL, @job_id BINARY(16) = NULL OUTPUT AS BEGIN DECLARE @retval INT declare @step_id int declare @step_name nvarchar(100) declare @step_command nvarchar(1024) declare @on_fail_action tinyint declare @on_success_action tinyint declare @schedule_name nvarchar(100) declare @comments nvarchar(100) SET NOCOUNT ON SELECT @retval = 1 -- 0 means success, 1 means failure set @step_id = 1 set @on_fail_action = 2 -- Return failure set @on_success_action = 1 -- Return success set @step_command = NULL /* ** Set default retries to every minute for 10 minutes. ** */ if @retryattempts = NULL and @retrydelay = 0 begin select @retryattempts = 10 select @retrydelay = 1 end BEGIN TRANSACTION -- Drop the job if it already exists IF EXISTS (SELECT * FROM msdb..sysjobs_view WHERE name = @name) begin exec @retval = msdb.dbo.sp_delete_job @job_name=@name if @@ERROR<>0 or @retval<>0 goto UNDO end -- Add the job EXECUTE @retval = msdb.dbo.sp_add_job @job_name = @name, @enabled = @enabled, @start_step_id = 1, @description = @description, @category_name = @category_name, @notify_level_eventlog = @loghistcompletionlevel, @notify_level_email = @emailcompletionlevel, @notify_email_operator_name = @emailoperatorname, @job_id = @job_id OUTPUT IF (@retval <> 0) BEGIN GOTO UNDO END -- Add startup message step if @failure_detection = 1 begin select @step_name = formatmessage(20528) select @comments = formatmessage(20529) -- Construct command based on subsystem type select @step_command = case UPPER(@subsystem) WHEN 'SNAPSHOT' THEN N'sp_MSadd_snapshot_history @perfmon_increment = 0, @agent_id = ' + convert (nvarchar(10), @agent_id) + N', @runstatus = 1, @comments = ''' + @comments + '''' WHEN 'LOGREADER' THEN N'sp_MSadd_logreader_history @perfmon_increment = 0, @agent_id = ' + convert (nvarchar(10), @agent_id) + N', @runstatus = 1, @comments = ''' + @comments + '''' WHEN 'DISTRIBUTION' THEN N'sp_MSadd_distribution_history @perfmon_increment = 0, @agent_id = ' + convert (nvarchar(10), @agent_id) + N', @runstatus = 1, @comments = ''' + @comments + '''' WHEN 'MERGE' THEN N'sp_MSadd_merge_history @perfmon_increment = 0, @agent_id = ' + convert (nvarchar(10),@agent_id) + N', @runstatus = 1, @comments = ''' + @comments + '''' end -- Add the job step EXECUTE @retval = msdb.dbo.sp_add_jobstep @job_id = @job_id, @step_id = @step_id, @step_name = @step_name, @command = @step_command, @cmdexec_success_code = @cmdexecsuccesscode, @on_success_action = 3, -- Goto next step @on_fail_action = 3, -- Goto next step @server = @server, @database_name = @databasename, @database_user_name = @username, @os_run_priority = @runpriority IF (@retval <> 0) BEGIN GOTO UNDO END set @step_id = @step_id + 1 set @on_fail_action = 3 -- Goto next step end -- Add the job step select @step_name = formatmessage(20530) EXECUTE @retval = msdb.dbo.sp_add_jobstep @job_id = @job_id, @step_id = @step_id, @step_name = @step_name, @subsystem = @subsystem, @command = @command, @cmdexec_success_code = @cmdexecsuccesscode, @on_success_action = @on_success_action, @on_fail_action = @on_fail_action, @server = @server, @database_name = @databasename, @database_user_name = @username, @retry_attempts = @retryattempts, @retry_interval = @retrydelay, @os_run_priority = @runpriority IF (@retval <> 0) BEGIN GOTO UNDO END -- Add failure message step if @failure_detection = 1 begin set @step_id = @step_id + 1 select @step_name = formatmessage(20531) -- Construct command select @step_command = N'sp_MSdetect_nonlogged_shutdown @subsystem = ''' + @subsystem + N''', @agent_id = ' + convert (nvarchar(10), @agent_id) -- Add the job step EXECUTE @retval = msdb.dbo.sp_add_jobstep @job_id = @job_id, @step_id = @step_id, @step_name = @step_name, @command = @step_command, @cmdexec_success_code = @cmdexecsuccesscode, @on_success_action = 2, -- Always quit with failure @server = @server, @database_name = @databasename, @database_user_name = @username, @os_run_priority = @runpriority IF (@retval <> 0) BEGIN GOTO UNDO END end -- Add the job schedule IF (@activestartdate = 0) SELECT @activestartdate = NULL IF (@activeenddate = 0) SELECT @activeenddate = NULL -- But if @activeenddate is NOT NULL, then @activestartdate cannot be allowed to be NULL either. Set it to today's date converted to the int format used yyyymmdd IF (@activeenddate IS NOT NULL AND @activestartdate IS NULL) SELECT @activestartdate=DATEPART(YYYY,getdate()) * 10000 + DATEPART(MM,getdate()) * 100 + DATEPART(DD,getdate()) -- But never let startdate be > end date IF (@activestartdate > @activeenddate) SELECT @activestartdate=@activeenddate IF (@activestarttimeofday = 0) SELECT @activestarttimeofday = NULL IF (@activeendtimeofday = 0) SELECT @activeendtimeofday = NULL IF (@freqtype <> 0x2) -- OnDemand tasks simply have no schedule in 7.0 BEGIN select @schedule_name = formatmessage(20532) EXECUTE @retval = msdb.dbo.sp_add_jobschedule @job_id = @job_id, @name = @schedule_name, @enabled = 1, @freq_type = @freqtype, @freq_interval = @freqinterval, @freq_subday_type = @freqsubtype, @freq_subday_interval = @freqsubinterval, @freq_relative_interval = @freqrelativeinterval, @freq_recurrence_factor = @freqrecurrencefactor, @active_start_date = @activestartdate, @active_end_date = @activeenddate, @active_start_time = @activestarttimeofday, @active_end_time = @activeendtimeofday IF (@retval <> 0) BEGIN GOTO UNDO END END -- And finally, add the job server EXECUTE @retval = msdb.dbo.sp_add_jobserver @job_id = @job_id, @server_name = '(local)' IF (@retval <> 0) BEGIN GOTO UNDO END COMMIT TRANSACTION -- If this is an autostart LogReader or Distribution or Merge job, add the [new] '-Continuous' paramter to the command IF (@freqtype = 0x40) AND ((UPPER(@subsystem) = 'LOGREADER') OR (UPPER(@subsystem) = 'DISTRIBUTION') OR (UPPER(@subsystem) = 'MERGE')) BEGIN UPDATE msdb.dbo.sysjobsteps SET command = command + ' -Continuous' WHERE (job_id = @job_id) AND ((@failure_detection = 0 and step_id = 1) or (@failure_detection = 1 and step_id = 2)) END -- If this is an autostart job, start it now (for backwards compatibility with 6.x SQLExecutive behaviour) IF (@freqtype = 0x40) EXECUTE msdb.dbo.sp_start_job @job_id = @job_id, @error_flag = 0 RETURN(0) UNDO: if @@TRANCOUNT = 1 ROLLBACK TRAN else COMMIT TRAN return(1) END go raiserror('Creating procedure sp_MScheck_subscription', 0,1) go CREATE PROCEDURE sp_MScheck_subscription ( @publication sysname, -- 1 Tran, 2 Merge @pub_type int )AS declare @merge_pubid uniqueidentifier declare @tran_pubid int if @pub_type = 2 BEGIN if not exists (select * from sysobjects where name = 'sysmergepublications') begin raiserror(20054, 16, -1) return (1) end select @merge_pubid = pubid from sysmergepublications where name=@publication and publisher=@@SERVERNAME and publisher_db=db_name() if @merge_pubid is NULL begin raiserror(20026, 16, -1, @publication) return (1) end if EXISTS (select * from sysmergesubscriptions where pubid=@merge_pubid and subid<>pubid) select 1 else select 0 END else -- if not merge, it has to be tran level. For other level, a generic error will be returned BEGIN if not exists (select * from sysobjects where name='syspublications') begin raiserror(20054, 16, -1) return (1) end select @tran_pubid = pubid from syspublications where name=@publication if @tran_pubid is NULL begin raiserror(20026, 16, -1, @publication) return (1) end if EXISTS (select * from syssubscriptions where (srvid <> -1) and artid in (select artid from sysarticles where pubid=@tran_pubid)) select 1 else select 0 END GO exec dbo.sp_MS_marksystemobject sp_MScheck_subscription go grant execute on dbo.sp_MScheck_subscription to public go raiserror('Creating procedure sp_replicationoption', 0,1) go CREATE PROCEDURE sp_replicationoption ( @optname sysname, @value nvarchar(5), @security_mode int = 0, @login sysname = 'sa', @password sysname = NULL, @reserved nvarchar(20) = NULL ) AS DECLARE @optbit bit DECLARE @osql_cmd1 nvarchar (255) DECLARE @osql_cmd_full nvarchar (255) DECLARE @osql_for_nt int DECLARE @install_path nvarchar (255) DECLARE @retcode int DECLARE @undo_install nvarchar(20) DECLARE @no_scripts nvarchar(10) DECLARE @platform_nt binary SELECT @platform_nt = 0x1 if is_srvrolemember('sysadmin') <> 1 BEGIN RAISERROR (15232, 14, -1) RETURN (1) END SELECT @no_scripts = 'no_scripts' SELECT @undo_install = 'undo_install' IF db_name() <> 'master' BEGIN RAISERROR(5001, 16,-1) GOTO FAILURE END IF LOWER(@optname) NOT IN ('transactional','merge') BEGIN RAISERROR(21014, 16, -1) GOTO FAILURE END IF LOWER(@value) NOT IN ('true','false') BEGIN RAISERROR(14137,16,-1) GOTO FAILURE END IF LOWER(@value) = 'true' SELECT @optbit = 1 ELSE SELECT @optbit = 0 /* ** Check if the option is set as required already */ IF @reserved <> @undo_install AND EXISTS (SELECT * FROM MSreplication_options WHERE optname = @optname AND value = @optbit) BEGIN IF LOWER(@value) = 'true' RAISERROR (21015, 10, -1, @optname) ELSE RAISERROR (21016, 10, -1, @optname) GOTO FAILURE END /* Install replication */ IF @optbit = 1 BEGIN IF LOWER(@reserved) = @no_scripts GOTO NO_SCRIPTS -- Set the flag for platform IF (( platform() & @platform_nt = @platform_nt )) SELECT @osql_for_nt = 1 ELSE SELECT @osql_for_nt = 0 /* ** Get installation path */ 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='' BEGIN GOTO FAILURE END /* ** Install replcom.sql and repltran.sql */ IF @security_mode = 1 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 ' -- Install replcom.sql -- bug24982 Only apply replcom.sql if it was not applied before. -- '-b' option will make osql stop at errors and return error code -- We must use this option. IF NOT EXISTS (SELECT * FROM MSreplication_options WHERE value = 1) BEGIN -- Initialize the Command IF (@osql_for_nt = 1) SELECT @osql_cmd_full = '" ' ELSE SELECT @osql_cmd_full = ' ' SELECT @osql_cmd_full = @osql_cmd_full + @osql_cmd1 + ' -dmaster' + ' -b ' + ' -i' + '"' + @install_path + '\install\replcom.sql"' + ' -o' + '"' + @install_path + '\install\replcom.out"' IF (@osql_for_nt = 1) SELECT @osql_cmd_full = @osql_cmd_full + ' "' EXEC @retcode = master..xp_cmdshell @osql_cmd_full IF @@ERROR<> 0 OR @retcode <> 0 BEGIN RAISERROR (14113, 16, -1, @osql_cmd_full, 'replcom.out') GOTO UNDO_INSTALL END END IF LOWER(@optname) = 'transactional' BEGIN -- Install repltran.sql IF (@osql_for_nt = 1) SELECT @osql_cmd_full = '" ' ELSE SELECT @osql_cmd_full = ' ' SELECT @osql_cmd_full = @osql_cmd_full + @osql_cmd1 + ' -dmaster' + ' -b ' + ' -i' + '"' + @install_path + '\install\repltran.sql"' + ' -o' + '"' + @install_path + '\install\repltran.out"' IF (@osql_for_nt = 1) SELECT @osql_cmd_full = @osql_cmd_full + ' "' EXEC @retcode = master..xp_cmdshell @osql_cmd_full IF @@ERROR<> 0 OR @retcode <> 0 BEGIN RAISERROR (14113, 16, -1, @osql_cmd_full, 'repltran.out') GOTO UNDO_INSTALL END END IF LOWER(@optname) = 'merge' BEGIN -- Install replmerg.sql IF (@osql_for_nt = 1) SELECT @osql_cmd_full = '" ' ELSE SELECT @osql_cmd_full = ' ' SELECT @osql_cmd_full = @osql_cmd_full + @osql_cmd1 + ' -dmaster' + ' -b ' + ' -i' + '"' + @install_path + '\install\replmerg.sql"' + ' -o' + '"' + @install_path + '\install\replmerg.out"' IF (@osql_for_nt = 1) SELECT @osql_cmd_full = @osql_cmd_full + ' "' EXEC @retcode = master..xp_cmdshell @osql_cmd_full IF @@ERROR<> 0 OR @retcode <> 0 BEGIN RAISERROR (14113, 16, -1, @osql_cmd_full, 'replmerg.out') GOTO UNDO_INSTALL END END NO_SCRIPTS: UPDATE MSreplication_options SET value = @optbit WHERE optname = @optname IF @@ERROR <> 0 BEGIN GOTO UNDO_INSTALL END END /* Uninstall replication */ ELSE BEGIN /* ** Make sure no distributor installed before dropping ** replication stored procedures */ IF EXISTS (SELECT * FROM master..sysservers WHERE srvstatus & 8 <> 0) BEGIN RAISERROR (21021, 16, -1) RETURN(1) END UPDATE MSreplication_options SET value = @optbit WHERE optname = @optname IF @@ERROR <> 0 BEGIN GOTO FAILURE END /* *********** Do not drop replication stored procs anymore. IF LOWER(@optname) = 'transactional' BEGIN if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSdrop_repltran') begin exec @retcode = dbo.sp_MSdrop_repltran if @@ERROR = 0 and @retcode = 0 drop procedure sp_MSdrop_repltran end END IF LOWER(@optname) = 'merge' BEGIN if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSdrop_replmerg') begin exec @retcode = dbo.sp_MSdrop_replmerg if @@ERROR = 0 and @retcode = 0 drop procedure sp_MSdrop_replmerg end END IF NOT EXISTS (SELECT * FROM MSreplication_options WHERE value = 1) BEGIN if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSdrop_replcom') begin exec @retcode = dbo.sp_MSdrop_replcom if @@ERROR = 0 and @retcode = 0 drop procedure sp_MSdrop_replcom end END */ END RETURN(0) UNDO_INSTALL: /* This is needed to drop the stored procedures that were created. */ EXEC dbo.sp_replicationoption @optname = @optname, @value = 'false', @reserved = @undo_install FAILURE: RETURN(1) GO exec dbo.sp_MS_marksystemobject sp_replicationoption go grant execute on dbo.sp_replicationoption to public raiserror('Creating procedure sp_helpreplicationoption', 0,1) go CREATE PROCEDURE sp_helpreplicationoption ( @optname sysname = NULL ) AS DECLARE @optbit bit DECLARE @retcode int IF @optname IS NOT NULL AND LOWER(@optname) NOT IN ('transactional','merge') BEGIN RAISERROR(21014, 16, -1) GOTO FAILURE END SELECT optname, value, major_version, minor_version, revision FROM MSreplication_options WHERE optname = @optname OR @optname = NULL RETURN(0) FAILURE: RETURN(1) GO exec dbo.sp_MS_marksystemobject sp_helpreplicationoption go grant execute on dbo.sp_helpreplicationoption to public raiserror('Creating procedure sp_MSgetreplnick', 0,1) GO create procedure sp_MSgetreplnick ( @server sysname = NULL, @db_name sysname = NULL, @pubid uniqueidentifier = NULL, @nickname int output ) as declare @srvid int if @db_name IS NULL select @db_name = db_name() /* Use 0 if the Server name is not passed in since it would be the local server */ if @server IS NULL select @srvid = 0 else select @srvid = max(srvid) from master..sysservers where UPPER(srvname) = UPPER(@server) if (@pubid IS NOT NULL) begin select @nickname = max(replnickname) from MSmerge_replinfo where repid in (select subid from sysmergesubscriptions where srvid = @srvid and db_name = @db_name and pubid = @pubid) end else begin select @nickname = max(replnickname) from MSmerge_replinfo where repid in (select subid from sysmergesubscriptions where srvid = @srvid and db_name = @db_name) end go exec dbo.sp_MS_marksystemobject sp_MSgetreplnick go grant execute on dbo.sp_MSgetreplnick to public raiserror('Creating procedure sp_MSreplcheck_publish', 0,1) go CREATE PROCEDURE sp_MSreplcheck_publish AS if is_srvrolemember('sysadmin') <> 1 and is_member ('db_owner') <> 1 BEGIN RAISERROR (21050, 14, -1) RETURN (1) END GO raiserror('Creating procedure sp_MSlocktable', 0,1) go CREATE PROCEDURE sp_MSlocktable @ownername sysname, @tablename sysname AS declare @ispublisher bit declare @retcode int declare @procname sysname declare @objid int declare @qualified_name nvarchar(255) select @qualified_name = QUOTENAME(@ownername) + '.' + QUOTENAME(@tablename) select @objid = object_id(@qualified_name) if @objid is NULL begin select @ispublisher = 0 select @qualified_name = QUOTENAME(@tablename) select @objid = object_id(@qualified_name) end else select @ispublisher = 1 exec dbo.sp_MSreplcheck_connection @objid = @objid select @procname = select_proc from sysmergearticles where objid = @objid and select_proc is not NULL exec @retcode = @procname @type = 7 -- exec ('select count(*) from ' + @ownername + '.' + @tablename + ' (tablock holdlock) where 1 = 2') go exec dbo.sp_MS_marksystemobject sp_MSlocktable go grant execute on dbo.sp_MSlocktable to public go raiserror('Creating procedure sp_MSenumcolumns', 0,1) go CREATE PROCEDURE sp_MSenumcolumns @pubid uniqueidentifier, @artid uniqueidentifier AS declare @retcode int declare @procname sysname select @procname = select_proc from sysmergearticles where pubid = @pubid and artid = @artid exec @retcode = @procname @type =6 go exec dbo.sp_MS_marksystemobject sp_MSenumcolumns go grant execute on dbo.sp_MSenumcolumns to public go /* ** Get pubid through connection_ID and check permission of this publication */ raiserror('Creating procedure sp_MSsetaccesslist', 0,1) go CREATE PROCEDURE sp_MSsetaccesslist @publication sysname, @publisher sysname, @publisher_db sysname AS declare @pubid uniqueidentifier select @pubid = pubid from sysmergepublications where name = @publication and UPPER(publisher)=UPPER(@publisher) and publisher_db=@publisher_db exec dbo.sp_MSreplcheck_connection @publication = @publication, @pubid = @pubid, @is_init = 1 go exec dbo.sp_MS_marksystemobject sp_MSsetaccesslist go grant execute on dbo.sp_MSsetaccesslist to public go raiserror('Creating procedure sp_MSreplcheck_connection', 0,1) go CREATE PROCEDURE sp_MSreplcheck_connection @publication sysname = NULL, @artid uniqueidentifier = NULL, @repid uniqueidentifier = NULL, @pubid uniqueidentifier = NULL, @objid int = NULL, @tablenick int = NULL, @is_init bit = 0 AS -- sysadmin or db_owner have access if is_srvrolemember('sysadmin') = 1 or is_member('db_owner') = 1 return 0 declare @retcode int declare @cached_id uniqueidentifier -- Need login_time to uniquely identify a connection. declare @login_time datetime select @login_time = login_time from master..sysprocesses where spid = @@spid select @cached_id = pubid from tempdb.dbo.MSpublisher_access where spid = @@spid and login_time = @login_time -- If spid with publication in the cache, return success. if @cached_id is null begin -- This stored procedure might be called by common sprocs at -- both the publisher and the subscriber by the merge agent -- The merge agent will call this sp with @is_init = 1 before -- any other calls to the publisher. All the other calls will -- set @is_init to 0. if @is_init = 0 begin RAISERROR (14126, 11, -1) return (1) end else begin exec @retcode = dbo.sp_MSreplcheck_pull @publication = @publication, @pubid = @pubid if @retcode <> 0 or @@error <> 0 return (1) end end else begin if @pubid is not null begin if @pubid <> @cached_id begin RAISERROR (14126, 11, -1) return (1) end end else if @tablenick is not null begin if not exists (select * from sysmergearticles where pubid = @cached_id and nickname = @tablenick) begin RAISERROR (14126, 11, -1) return (1) end end else if @artid is not null begin if not exists (select * from sysmergearticles where pubid = @cached_id and artid = @artid) begin RAISERROR (14126, 11, -1) return (1) end end else if @objid is not null begin if not exists (select * from sysmergearticles where pubid = @cached_id and objid=@objid) begin RAISERROR (14126, 11, -1) return (1) end end else if @publication is not null begin if not exists (select * from sysmergepublications where pubid = @cached_id and name = @publication) begin RAISERROR (14126, 11, -1) return (1) end end else if @repid is not null begin if not exists (select * from sysmergesubscriptions where pubid = @cached_id and subid = @repid) begin RAISERROR (14126, 11, -1) return (1) end end end GO exec dbo.sp_MS_marksystemobject sp_MSreplcheck_connection go grant execute on dbo.sp_MSreplcheck_connection to public go raiserror('Creating procedure sp_MSreplcheck_pull', 0,1) go CREATE PROCEDURE sp_MSreplcheck_pull ( @publication sysname, @raise_fatal_error bit = 1, @pubid uniqueidentifier = NULL ) AS -- sysadmin or db_owner have access if is_srvrolemember('sysadmin') = 1 or is_member('db_owner') = 1 return 0 -- Need login_time to uniquely identify a connection. declare @login_time datetime select @login_time = login_time from master..sysprocesses where spid = @@spid -- If spid with publication in the cache, return success. if exists (select * from tempdb.dbo.MSpublisher_access where spid = @@spid and login_time = @login_time and db_id = db_id() and publication = @publication) return (0) declare @has_access bit DECLARE @distribdb sysname DECLARE @distproc nvarchar (255) DECLARE @retcode int DECLARE @dist_rpcname sysname DECLARE @database sysname declare @login sysname select @login = suser_sname(suser_sid()) select @database = db_name() EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @dist_rpcname OUTPUT, @distribdb = @distribdb OUTPUT IF @retcode <> 0 or @@error <> 0 BEGIN RAISERROR (14071, 16, -1) return (1) END IF @retcode <> 0 OR @distribdb IS NULL OR @dist_rpcname IS NULL BEGIN RAISERROR (14071, 16, -1) return(1) END SELECT @distproc = RTRIM(@dist_rpcname) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSpublication_access' EXEC @retcode = @distproc @publisher = @@SERVERNAME, @publisher_db = @database, @publication = @publication, @operation = 'check', @login = @login, @has_access = @has_access output IF @@error <> 0 OR @retcode <> 0 BEGIN RAISERROR (14042, 16, -1) return (1) END if @has_access = 0 begin -- We don't have access if we reach here, return error IF @raise_fatal_error = 1 RAISERROR (21049, 14, -1, @login, @publication) ELSE RAISERROR (21049, 10, -1, @login, @publication) return(1) end ADD_CACHE: -- If we are here, we know that the connection has access and is not in the cache -- add it in to the cache. -- Clear the cache to keep it small. exec @retcode = dbo.sp_MSflush_access_cache if @retcode <> 0 or @@error <> 0 return (1) insert tempdb.dbo.MSpublisher_access (spid, db_id, publication, login_time, pubid) values (@@spid, db_id(), @publication, @login_time, @pubid) if @@error <> 0 return (1) return (0) GO raiserror('Creating procedure sp_MSreplcheck_qv', 0, 1) GO create procedure sp_MSreplcheck_qv as begin set nocount on declare @qv_replication varchar(10) declare @qv_engine varchar(10) declare @qv_value_replication integer declare @qv_value_engine integer select @qv_replication = '2745196162', @qv_engine = '845129433' exec @qv_value_replication = master.dbo.xp_qv @qv_replication if @@ERROR <> 0 select @qv_value_replication = 1 exec @qv_value_engine = master.dbo.xp_qv @qv_engine if @@ERROR <> 0 select @qv_value_engine = 1 -- magic number 1 assumes least common setting on all failure states select isnull( @qv_value_replication, 1 ) as VALUE_REPLICATION, isnull( @qv_value_engine, 1 ) as VALUE_ENGINE end go exec dbo.sp_MS_marksystemobject sp_MSreplcheck_qv go grant execute on dbo.sp_MSreplcheck_qv to public 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 @schemaguid uniqueidentifier 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 from sysmergepublications pubs, sysmergesubscriptions subs where pubs.name LIKE @publication AND ((@publisher = N'%') 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 while (@@fetch_status<>-1) BEGIN update MSmerge_replinfo set schemaversion=-1, recgen = NULL, recguid=NULL, sentgen=NULL, sentguid = NULL where repid=@subid -- use -1 to replace 0 fetch next from SYN_CUR into @subid -- 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 exec dbo.sp_MS_marksystemobject sp_reinitmergepullsubscription go grant execute on dbo.sp_reinitmergepullsubscription to public raiserror('Creating procedure sp_MSreplcheck_subscribe', 0,1) go CREATE PROCEDURE sp_MSreplcheck_subscribe AS /* ** Only the System Administratr (SA) or the Database Owner (dbo) ** can subscribe from the subscribing database. */ if is_srvrolemember('sysadmin') <> 1 and is_member ('db_owner') <> 1 BEGIN RAISERROR (21050, 14, -1) RETURN (1) END GO raiserror('Creating procedure sp_MSreplicationcompatlevel', 0,1) GO create procedure sp_MSreplicationcompatlevel @dbname sysname, @cmptlevel float(8) As declare @is_distdb smallint select @is_distdb = 0 IF EXISTS (select * from msdb..sysobjects where name='MSdistributiondbs') begin IF EXISTS (SELECT * FROM msdb..MSdistributiondbs where name=@dbname) select @is_distdb = 1 end /* ** Parameter check ** @dbname */ IF NOT EXISTS (SELECT * FROM master.dbo.sysdatabases WHERE name = @dbname) BEGIN RAISERROR(15010, 16, -1, @dbname) RETURN(2) END /* ** Parameter check. NOTE ** @cmptlevel */ IF @cmptlevel<6.0 BEGIN RAISERROR(20060,16,-1) RETURN(2) END /* ** If cmptlevel is lower than 7.0, special attention should be paid. ** If current database is a distribution database or is involed in merge ** replication, then it can not be set to a level lower than 7.0. */ create table #tmp (any_merge smallint NOT NULL) insert into #tmp exec ('select count(*) from ' + @dbname + '..sysobjects where name=' + '''sysmergesubscriptions''' ) if (exists(select any_merge from #tmp where any_merge>0) OR @is_distdb = 1) AND (@cmptlevel<7.0) begin drop table #tmp return 1 end else begin drop table #tmp return 0 end go exec dbo.sp_MS_marksystemobject sp_MSreplicationcompatlevel go raiserror('Creating procedure sp_MSgenreplnickname', 0,1) GO create procedure sp_MSgenreplnickname @srcguid uniqueidentifier, /* Source Guid */ @repnick int output /* nickname */ as declare @binguid binary(16) declare @nickname int set @binguid = convert(binary(16), @srcguid) select @nickname = convert(int, convert(binary(4),substring( convert(nchar(8),@binguid), 1, 2))) while exists (select replnickname from MSmerge_replinfo where replnickname = @nickname) select @nickname = @nickname + 1 select @repnick = @nickname go exec dbo.sp_MS_marksystemobject sp_MSgenreplnickname go grant execute on dbo.sp_MSgenreplnickname to public raiserror('Creating procedure sp_MSmergesubscribedb', 0,1) GO CREATE PROCEDURE sp_MSmergesubscribedb( @value sysname ) AS SET NOCOUNT ON /* ** Declarations. */ declare @retcode int /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) /* ** Initialization */ /* ** Parameter check ** @value */ IF LOWER(@value) NOT IN ('true','false') BEGIN RAISERROR(14137,16,-1) RETURN(1) END IF LOWER(@value) = 'true' BEGIN execute @retcode = dbo.sp_MScreate_mergesystables if @@ERROR <> 0 or @retcode <> 0 begin return (1) end END -- We assume we will do nothing about disabling a subscriber GO exec dbo.sp_MS_marksystemobject sp_MSmergesubscribedb go grant execute on dbo.sp_MSmergesubscribedb to public 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) /* 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 raiserror('Creating procedure sp_MSenumtranpublications', 0,1) go CREATE PROCEDURE sp_MSenumtranpublications as set nocount on select db_name(), name, 1, immediate_sync, allow_pull, allow_anonymous, enabled_for_internet, repl_freq, immediate_sync_ready, allow_sync_tran, independent_agent, is_member('db_owner'), 0, -- thirdparty 'Microsoft SQL Server', @@servername, description, convert(sysname, null) from syspublications pubs where exists (select * from sysarticles art where pubs.pubid = art.pubid) and status <> 0 go raiserror('Creating procedure sp_MSenummergepublications', 0,1) go CREATE PROCEDURE sp_MSenummergepublications as set nocount on select db_name(), name, 2, 1, allow_pull, allow_anonymous, enabled_for_internet, 0, snapshot_ready, 0, 1, is_member('db_owner'), 0, --thirdparty 'Microsoft SQL Server', publisher, description, convert(sysname, null) from sysmergepublications where status <> 0 go raiserror('Creating procedure sp_MSenum3rdpartypublications', 0,1) go CREATE PROCEDURE sp_MSenum3rdpartypublications as set nocount on select pubs.publisher_db, publication, case when publication_type <> 2 then 1 else 2 end, --replication_type, 1 tran, 2 merge ; pub type 0 tran 1 snapshot, 2 merge immediate_sync, allow_pull, allow_anonymous, 0, --enabled_for_internet, case when publication_type = 0 then 0 else 1 end, --repl_freq, 1, --immediate_sync_ready, always return 1 so that UI will not warn 0, -- allow_sync_tran, independent_agent, is_member('db_owner'), 1, --thirdparty pubs.vendor_name, srv.srvname, pubs.description, db_name() from MSpublications pubs, master..sysservers srv where exists (select * from MSarticles art where pubs.publication_id = art.publication_id) and thirdparty_flag <> 0 and publisher_id = srvid go dump tran master with no_log 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, subid = NULL 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 raiserror('Creating procedure sp_addpullsubscription', 0,1) go CREATE PROCEDURE sp_addpullsubscription ( @publisher sysname, @publisher_db sysname, @publication sysname, /* publication name */ @independent_agent nvarchar(5) = 'true', /* true or false */ @subscription_type nvarchar(9) = 'anonymous', /* subscription_type, pull or anonymous */ @description nvarchar(100) = NULL, -- SyncTran @update_mode nvarchar(15) = 'read only', -- Can be 'read only', 'sync tran' @immediate_sync bit = 1 ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @retcode int DECLARE @subscription_type_id int /* 1 = pull, 2 = anonymous */ DECLARE @independent_agent_id bit -- SyncTran DECLARE @update_mode_id tinyint /* ** 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) /* ** 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 @publication = 'all' BEGIN RAISERROR (14136, 16, -1) RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) 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: @subscription_type ** The @status value can be: ** ** type_id type ** ====== ======== ** 0 push ** 1 pull ** 2 anonymous ** ** Note: @subscription_type = push is only used by distribution agents */ IF @subscription_type IS NULL OR LOWER(@subscription_type) NOT IN ('push', 'pull','anonymous') BEGIN RAISERROR (20016, 16, -1) RETURN (1) END IF LOWER(@subscription_type) = 'pull' SELECT @subscription_type_id = 1 ELSE IF LOWER(@subscription_type) = 'anonymous' SELECT @subscription_type_id = 2 ELSE SELECT @subscription_type_id = 0 IF @independent_agent_id = 0 AND @subscription_type_id = 2 BEGIN RAISERROR (21026, 16, -1) RETURN (1) END -- SyncTran /* ** Parameter check: @update_mode */ IF @update_mode IS NULL OR LOWER(@update_mode) NOT IN ('read only', 'sync tran') BEGIN RAISERROR (20502, 16, -1, '@update_mode') RETURN (1) END IF LOWER(@update_mode) = 'sync tran' begin SELECT @update_mode_id = 1 if @subscription_type_id = 2 -- Anonymous subscriptions should not be allowed to begin -- subscribe with 'synctran option' RAISERROR (21057, 16, -1) RETURN (1) end end ELSE SELECT @update_mode_id = 0 -- SyncTran begin tran save TRAN addpullsubscription /* ** Check to see if MSreplication_subscriptions and MSsubscription_properties ** tables exists. ** If not, create it. */ exec @retcode = dbo.sp_MScreate_sub_tables @tran_sub_table = 1, @property_table = 1 IF @@ERROR <> 0 or @retcode <> 0 goto UNDO /* ** Check to make sure that the subscription does not already exist */ -- Delete the push subscription entry first. If may be obsolete and left by -- defunct push agents delete MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication and subscription_type = 0 if @@error <> 0 goto UNDO -- It is not allowed to subscribe to the same publication twice even with -- differnet publication type. IF EXISTS (SELECT * FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication) /* OR -- If the subscription is already added by the distribution agent (@independent_agent_id = 0 AND (publication IS NULL OR publication = ''))) AND independent_agent = @independent_agent_id AND subscription_type = @subscription_type_id) */ BEGIN RAISERROR (14058, 16, -1) GOTO UNDO END /* ** Add the subscription */ INSERT MSreplication_subscriptions (publisher, publisher_db, publication, independent_agent, subscription_type, distribution_agent, description, time, transaction_timestamp, -- SyncTran update_mode, immediate_sync) VALUES (@publisher, @publisher_db, @publication, @independent_agent_id, @subscription_type_id, NULL, @description, getdate(), 0, -- SyncTran @update_mode_id, @immediate_sync ) IF @@ERROR <> 0 BEGIN RAISERROR (14057, 16, -1) GOTO UNDO END COMMIT TRAN RETURN (0) UNDO: IF @@TRANCOUNT > 0 begin ROLLBACK TRAN addpullsubscription COMMIT TRAN end return 1 go raiserror('Creating procedure sp_addpullsubscription_agent', 0,1) go CREATE PROCEDURE sp_addpullsubscription_agent ( @publisher sysname, @publisher_db sysname, @publication sysname, /* publication name */ @subscriber sysname = NULL, @subscriber_db sysname = NULL, @subscriber_security_mode int = NULL, /* 0 standard; 1 integrated */ @subscriber_login sysname = NULL, @subscriber_password sysname = NULL, @distributor sysname = @publisher, @distribution_db sysname = NULL, @distributor_security_mode int = 0, @distributor_login sysname = 'sa', @distributor_password sysname = NULL, @optional_command_line nvarchar(4000) = '', @frequency_type int = 2 , /* 2== OnDemand */ @frequency_interval int = 1, @frequency_relative_interval int = 1, @frequency_recurrence_factor int = 1, @frequency_subday int = 1, @frequency_subday_interval int = 1 , @active_start_time_of_day int = 0, @active_end_time_of_day int = 0, @active_start_date int = 0, @active_end_date int =0, @distribution_jobid binary(16) = NULL OUTPUT, @encrypted_distributor_password bit = 0, @enabled_for_syncmgr nvarchar(5) = 'false', /* Enabled for SYNCMGR: true or false */ @ftp_address sysname = NULL, @ftp_port int = NULL, @ftp_login sysname = NULL, @ftp_password sysname = NULL ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @command nvarchar(4000) DECLARE @name nvarchar(255) DECLARE @retcode int DECLARE @subscription_type_id int /* 1 = pull, 2 = anonymous */ DECLARE @independent_agent_id bit DECLARE @distribution_agent nvarchar(100) DECLARE @category_name sysname DECLARE @platform_nt binary DECLARE @subscriber_enc_password sysname select @platform_nt = 0x1 /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) /* ** Initializations. */ -- Set null @optional_command_line to empty string to avoid string concat problem if @optional_command_line is null set @optional_command_line = '' IF @distributor_password = N'' select @distributor_password = NULL IF @ftp_password = N'' select @ftp_password = NULL /* ** 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 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 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 EXECUTE @retcode = dbo.sp_validname @publication IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) /* ** Parameter Check: @subscriber and @subscriber_db */ if @subscriber IS NULL or rtrim(@subscriber) = '' SELECT @subscriber = @@SERVERNAME if @subscriber_db IS NULL or rtrim(@subscriber_db) = '' SELECT @subscriber_db = DB_NAME() EXECUTE @retcode = dbo.sp_validname @subscriber IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) EXECUTE @retcode = dbo.sp_validname @subscriber_db IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) /* ** Check to see if MSreplictaion_subscriptions table exists. ** If so, copy it into the temp table */ IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND name = 'MSreplication_subscriptions') BEGIN RAISERROR (20017, 16, -1) RETURN (1) END /* ** Check to make sure that the subscription does exist */ IF NOT EXISTS (SELECT * FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication) BEGIN RAISERROR (20017, 16, -1) RETURN (1) END SELECT @distribution_agent = NULL SELECT @independent_agent_id = independent_agent, @subscription_type_id = subscription_type, @distribution_agent = distribution_agent FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication /* Distribution agent for push subscriptions is at distributor side */ IF @subscription_type_id = 0 BEGIN RAISERROR (21001, 16, -1) RETURN (1) END IF @distribution_agent IS NOT NULL BEGIN RAISERROR (21002, 11, -1, @distribution_agent) RETURN (1) END -- Parameter check: @subscriber_security_mode if @subscriber_security_mode is null begin if ( platform() & @platform_nt ) = @platform_nt select @subscriber_security_mode = 1 else select @subscriber_security_mode = 0 end if ( ( platform() & @platform_nt ) <> @platform_nt and @subscriber_security_mode = 1 ) begin RAISERROR(21038, 16, -1) RETURN (1) end if (@subscription_type_id <> 0) begin if (@subscriber_security_mode = 0) and (@subscriber_login IS NULL or rtrim(@subscriber_login) = '') begin raiserror(3217, 16, -1, '@subscriber_login') return (1) end end IF NOT EXISTS (select * from sysobjects where name = 'MSsubscription_properties' and type = 'U') begin raiserror(14027, 16, -1, 'The subscription properties table ''MSsubscription_properties''') return (1) end /* ** Construct unique name */ if @subscriber is NULL select @subscriber = '' if @subscriber_db is NULL select @subscriber_db = '' SELECT @name = CONVERT(nvarchar(23),@publisher ) + '-' + CONVERT(nvarchar(23),@publisher_db) + '-' + CONVERT(nvarchar(23),@publication) + '-' + CONVERT(nvarchar(23),@subscriber) + '-' + CONVERT(nvarchar(23),@subscriber_db) + '- 0' BEGIN TRAN /* ** If the publication is independent agent type or it is the first ** subscription on the non independent agent publications. */ IF @independent_agent_id = 1 OR NOT EXISTS (SELECT * FROM MSreplication_subscriptions WHERE UPPER(@publisher) = UPPER(publisher) and @publisher_db = publisher_db and agent_id IS NOT NULL and independent_agent = 0) BEGIN /* Construct agent command */ SELECT @command = '-Publisher ' + @publisher + ' ' SELECT @command = @command + '-PublisherDB ' + QUOTENAME(@publisher_db) + ' ' IF @independent_agent_id = 1 SELECT @command = @command + '-Publication ' + QUOTENAME(@publication) + ' ' SELECT @command = @command + '-Distributor ' + QUOTENAME(@distributor) + ' ' /* Use -Xdatabase to save command line space We can not use -Xserver for distribution because SQLExec will valid the server to be in sysservers. SELECT @command = @command + '-DistributionDB ' + QUOTENAME(@distribution_db) + ' ' */ SELECT @command = @command + '-SubscriptionType ' + convert(nvarchar(10),@subscription_type_id) + ' ' SELECT @command = @command + '-Subscriber ' + QUOTENAME(@subscriber) + ' ' select @command = @command + '-SubscriberSecurityMode ' + convert(nvarchar(10),@subscriber_security_mode) + ' ' if @subscriber_login is not NULL select @command = @command + '-SubscriberLogin ' + quotename(@subscriber_login) + ' ' if @subscriber_password is not NULL begin set @subscriber_enc_password = @subscriber_password exec @retcode = master.dbo.xp_repl_encrypt @subscriber_enc_password OUTPUT select @command = @command + '-SubscriberEncryptedPassword ' + quotename(@subscriber_enc_password) + ' ' end SELECT @command = @command + '-SubscriberDB ' + QUOTENAME(@subscriber_db) + ' ' /* ** make sure the command line is not truncated */ /* Use datalength because len doesn't count the last space in @command */ IF (datalength(@command) + datalength(@optional_command_line)) > 8000 BEGIN RAISERROR(20018, 16, -1) RETURN(1) END SELECT @command = @command + @optional_command_line -- Get Distribution category name (assumes category_id = 10) select @category_name = name FROM msdb.dbo.syscategories where category_id = 10 EXEC @retcode = dbo.sp_MSadd_repl_job @name = @name, @subsystem = 'Distribution', @server = @@SERVERNAME, @databasename = @distribution_db, @enabled = 1, @freqtype = @frequency_type, @freqinterval = @frequency_interval, @freqsubtype = @frequency_subday, @freqsubinterval = @frequency_subday_interval, @freqrelativeinterval = @frequency_relative_interval, @freqrecurrencefactor = @frequency_recurrence_factor, @activestartdate = @active_start_date, @activeenddate = @active_end_date, @activestarttimeofday = @active_start_time_of_day, @activeendtimeofday = @active_end_time_of_day, @command = @command, @category_name = @category_name, @retryattempts = 10, @retrydelay = 1, @job_id = @distribution_jobid OUTPUT IF @@ERROR <> 0 or @retcode <> 0 BEGIN IF @@TRANCOUNT = 1 ROLLBACK TRAN ELSE COMMIT TRAN RETURN(1) END END if (@subscription_type_id = 1) OR (@subscription_type_id = 2) BEGIN IF NOT EXISTS (select * from MSsubscription_properties where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication) BEGIN -- 0 transactional -- 1 snapshot -- 2 merge IF (@encrypted_distributor_password = 0) -- Encrypt the password BEGIN EXEC @retcode = master.dbo.xp_repl_encrypt @distributor_password OUTPUT IF @@error <> 0 OR @retcode <> 0 return 1 END INSERT INTO MSsubscription_properties (publisher, publisher_db, publication, publication_type, publisher_login,publisher_password, publisher_security_mode, distributor, distributor_login, distributor_password, distributor_security_mode, ftp_address, ftp_port, ftp_login, ftp_password) values (@publisher, @publisher_db, @publication, 0, NULL, NULL, 1, @distributor, @distributor_login, @distributor_password, @distributor_security_mode, @ftp_address, @ftp_port, @ftp_login, @ftp_password) IF @@ERROR <> 0 BEGIN IF @@TRANCOUNT = 1 ROLLBACK TRAN ELSE COMMIT TRAN RETURN(1) END END ELSE BEGIN update MSsubscription_properties set distributor = @distributor, distributor_login = @distributor_login, distributor_password = @distributor_password, distributor_security_mode = @distributor_security_mode where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication END IF @@ERROR <> 0 BEGIN IF @@TRANCOUNT = 1 ROLLBACK TRAN ELSE COMMIT TRAN RETURN(1) END END /* If we do not have independent agents , i.e. independent_agent=0, but there is already a row for that publisher and that publisher database with a NOT null distribution_agent_id, then set the @distribution_jobid to that id. Note that if there are no rows returned, the value of the variable does not change, which is what we want. There should never be more than one row ever returned for this query - but will use TOP 1 to insist that is the case. */ SELECT DISTINCT @distribution_jobid=agent_id FROM MSreplication_subscriptions WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND agent_id IS NOT NULL AND independent_agent=0 UPDATE MSreplication_subscriptions SET distribution_agent = @name, agent_id = @distribution_jobid WHERE UPPER(publisher) = UPPER(@publisher) AND publisher_db = @publisher_db AND publication = @publication AND (subscription_type = 1 /* pull*/ OR subscription_type = 2) /*anonymous*/ IF @@ERROR <> 0 BEGIN IF @@TRANCOUNT = 1 ROLLBACK TRAN ELSE COMMIT TRAN RETURN(1) END /* Conditional support for MobileSync */ if LOWER(@enabled_for_syncmgr) = 'true' BEGIN /* Call sp_MSregistersubscription so that the subscription can be synchronized via MobileSync etc. */ declare @subscription_id uniqueidentifier set @subscription_id = convert(uniqueidentifier, @distribution_jobid) exec @retcode = dbo.sp_MSregistersubscription @replication_type = 1, @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @subscriber = @subscriber, @subscriber_db = @subscriber_db, @subscriber_security_mode = @subscriber_security_mode, @subscriber_login = @subscriber_login, @subscriber_password = @subscriber_password, @distributor = @distributor, @subscription_id = @subscription_id, @independent_agent = @independent_agent_id, @subscription_type = @subscription_type_id IF @@ERROR <> 0 or @retcode <> 0 BEGIN IF @@TRANCOUNT = 1 ROLLBACK TRAN ELSE COMMIT TRAN RETURN(1) END END COMMIT TRAN RETURN(0) GO raiserror('Creating procedure sp_helpsubscription_properties', 0,1) go CREATE PROCEDURE sp_helpsubscription_properties @publisher sysname = '%', @publisher_db sysname = '%', @publication sysname = '%', @publication_type int = NULL AS SET NOCOUNT ON declare @retcode int /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) /* ** The logic is added here for the case where MSsubscription_properties table does not exist ** or relevant entry is not added because sp_addmergepullsubscription_agent or sp_addsubscription_agent ** is not called. */ IF NOT EXISTS (select * from sysobjects where name = 'MSsubscription_properties' and type = 'U') begin return (0) end IF (@publication IS NULL) OR (@publication = '') select @publication = '%' IF @publication_type IS NULL BEGIN select publisher, publisher_db, publication, publication_type, publisher_login, publisher_password, publisher_security_mode, distributor, distributor_login, distributor_password, distributor_security_mode, ftp_address, isnull(ftp_port, 0), ftp_login, ftp_password from MSsubscription_properties where ((@publisher = N'%') or (UPPER(publisher) = UPPER(@publisher))) and publisher_db like @publisher_db and publication like @publication END ELSE BEGIN select publisher, publisher_db, publication, publication_type, publisher_login, publisher_password, publisher_security_mode, distributor, distributor_login, distributor_password, distributor_security_mode, ftp_address, isnull(ftp_port, 0), ftp_login, ftp_password from MSsubscription_properties where ((@publisher = N'%') or (UPPER(publisher) = UPPER(@publisher))) and publisher_db like @publisher_db and publication like @publication and publication_type = @publication_type END return (0) GO EXEC dbo.sp_MS_marksystemobject sp_helpsubscription_properties GO raiserror('Creating procedure sp_change_subscription_properties', 0,1) go CREATE PROCEDURE sp_change_subscription_properties @publisher sysname, @publisher_db sysname, @publication sysname, @property sysname, @value sysname AS SET NOCOUNT ON DECLARE @command nvarchar(2000) DECLARE @column_to_update nvarchar(64) DECLARE @value_string nvarchar(255) DECLARE @retcode int /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) IF NOT EXISTS (select * from sysobjects where name = 'MSsubscription_properties' and type = 'U') begin raiserror(14027, 16, -1, 'The subscription properties table ''MSsubscription_properties''') return (1) end if (@publisher is null) begin raiserror(14043, 16, -1, '@publisher') return (1) end if(@publisher_db is null) begin raiserror(14043, 16, -1, '@publisher_db') return (1) end IF (@property IS NULL) begin raiserror(14043, 16, -1, '@property') return (1) end ELSE IF (lower(@property) = 'publisher_login') select @column_to_update = 'publisher_login' ELSE IF (lower(@property) = 'publisher_password') begin select @column_to_update = 'publisher_password' EXEC @retcode = master.dbo.xp_repl_encrypt @value OUTPUT IF @@error <> 0 OR @retcode <> 0 return 1 end ELSE IF (lower(@property) = 'publisher_security_mode') select @column_to_update = 'publisher_security_mode' ELSE IF (lower(@property) = 'distributor') select @column_to_update = 'distributor' ELSE IF (lower(@property) = 'distributor_login') select @column_to_update = 'distributor_login' ELSE IF (lower(@property) = 'distributor_password') begin select @column_to_update = 'distributor_password' EXEC @retcode = master.dbo.xp_repl_encrypt @value OUTPUT IF @@error <> 0 OR @retcode <> 0 return 1 end ELSE IF (lower(@property) = 'distributor_security_mode') select @column_to_update = 'distributor_security_mode' ELSE IF (lower(@property) = 'ftp_address') select @column_to_update = 'ftp_address' ELSE IF (lower(@property) = 'ftp_port') select @column_to_update = 'ftp_port' ELSE IF (lower(@property) = 'ftp_login') select @column_to_update = 'ftp_login' ELSE IF (lower(@property) = 'ftp_password') select @column_to_update = 'ftp_password' ELSE BEGIN raiserror (3217, 16, -1, '@property') return(1) END IF (lower(@property) = 'distributor_security_mode') OR (lower(@property) = 'publisher_security_mode') BEGIN IF NOT ( @value = 0 or @value = 1 or (@value = 2 and lower(@property) = 'publisher_security_mode' )) BEGIN raiserror(3217, 16, -1, '@value') return(1) END select @value_string = convert(nvarchar(1), @value) END ELSE BEGIN IF (@value IS NULL) select @value_string = 'NULL' ELSE select @value_string = 'N''' + rtrim(@value) + '''' END if (@publication is null) or (@publication = '') begin select @publication = '%' end -- Password is encrypted. Cannot use dynamic query (exec (@cmd)) to update -- otherwise, the chars will be convert to '???' IF (lower(@property) = 'distributor_password') begin update MSsubscription_properties set distributor_password = @value where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication like @publication end ELSE IF (lower(@property) = 'publisher_password') begin update MSsubscription_properties set publisher_password = @value where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication like @publication end else begin select @command = N'update MSsubscription_properties set ' + @column_to_update + '= ' + @value_string + ' where UPPER(publisher) = UPPER(''' + @publisher + ''') and publisher_db = ''' + @publisher_db + ''' and publication like ''' + @publication + '''' EXEC (@command) end if @@error <> 0 return (1) else return (0) GO EXEC dbo.sp_MS_marksystemobject sp_change_subscription_properties GO grant execute on dbo.sp_change_subscription_properties to public raiserror('Creating procedure sp_MSget_pullsubsagent_owner', 0,1) go CREATE PROCEDURE sp_MSget_pullsubsagent_owner ( @publisher sysname, @publisher_db sysname, @publication sysname, /* publication name */ @owner_sid varbinary(85) OUTPUT ) AS declare @job_id uniqueidentifier set nocount on select @owner_sid = null if exists (select * from sysobjects where type = 'U' and name = 'MSreplication_subscriptions') begin -- Get the job_id corresponding to the publication select @job_id = agent_id from MSreplication_subscriptions where upper(@publisher) = upper(publisher) and @publisher_db = publisher_db and @publication = publication -- Using the job_id in MSsubscription properties to get the owner_sid -- in msdb..sysjobs select @owner_sid = owner_sid from msdb..sysjobs where @job_id = job_id end go exec dbo.sp_MS_marksystemobject 'sp_MSget_pullsubsagent_owner' 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 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 IF 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 raiserror('Creating procedure sp_helppullsubscription', 0,1, 0,1) go CREATE PROCEDURE sp_helppullsubscription ( @publisher sysname = '%', @publisher_db sysname = '%', @publication sysname = '%', @show_push nvarchar(5) = 'false' ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @command nvarchar(255) DECLARE @name nvarchar(255) DECLARE @retcode int DECLARE @show_push_bit bit DECLARE @push int declare @subscriber sysname declare @subscriber_db sysname declare @publisher_local sysname declare @publisher_db_local sysname declare @publication_local sysname declare @subscription_name nvarchar(1000) declare @regkey nvarchar(1000) declare @syncmgr_keyexist int declare @helpsubscriptioncursor_open int SELECT @push = 0 /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) /* ** Initializations. */ set @subscriber = @@SERVERNAME set @subscriber_db = DB_NAME() /* ** 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 <> '%' BEGIN EXECUTE @retcode = dbo.sp_validname @publisher IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) END IF @publication <> '%' BEGIN EXECUTE @retcode = dbo.sp_validname @publication IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) END IF @show_push IS NOT NULL AND LOWER(@show_push) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@show_push') RETURN (1) END IF LOWER(@show_push) = 'false' SELECT @show_push_bit = 0 IF LOWER(@show_push) = 'true' SELECT @show_push_bit = 1 IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'U' AND name = 'MSreplication_subscriptions') RETURN (0) create table #helpsubscription ( 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, enabled_for_syncmgr int NULL ) insert into #helpsubscription select *, 0 from MSreplication_subscriptions WHERE ((@publisher = N'%') OR (UPPER(publisher) = UPPER(@publisher))) AND publisher_db LIKE @publisher_db AND publication LIKE @publication AND (subscription_type <> @push OR @show_push_bit = 1) ORDER BY publisher, publisher_db, publication declare #helpsubscriptioncursor CURSOR LOCAL FAST_FORWARD FOR select DISTINCT publisher, publisher_db, publication FROM #helpsubscription 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 #helpsubscription set enabled_for_syncmgr = @syncmgr_keyexist 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 /* ** Get the result ** ** Note: have to return meta data */ SELECT 'publisher' = publisher, 'publisher database' = publisher_db, 'publication' = publication, 'independent_agent' = independent_agent, 'subscription type' = subscription_type, 'distribution agent' = distribution_agent, 'publication description' = description, 'last updating time' = convert(nvarchar(12), time, 112) + substring(convert(nvarchar(24), time, 121), 11,13), 'subscription_name' = publisher + ':' + publisher_db + ':' + publication, 'last transaction timestamp' = transaction_timestamp, -- SyncTran 'update_mode' = update_mode, 'distribution agent job_id' = agent_id, 'enabled for syncmgr' = enabled_for_syncmgr, 'subscription guid' = subscription_guid, 'subid ' = subid, 'immediate_sync' = immediate_sync FROM #helpsubscription drop table #helpsubscription if (@helpsubscriptioncursor_open = 1) begin close #helpsubscriptioncursor deallocate #helpsubscriptioncursor end drop table #syncmgr_keyexist GO raiserror('Creating procedure sp_MStable_has_unique_index', 0,1) go create procedure sp_MStable_has_unique_index @tabid int as begin /* ** Returns id of unique index, if it exists, else 0 */ declare @indid int if (ObjectProperty(@tabid, 'IsTable') = 1) and (ObjectProperty(@tabid, 'TableHasIndex') = 1) begin -- First get the primary index id. See bug 52471 select @indid = i.indid from sysindexes i where -- get the primary key index (i.status & 2048) <> 0 and i.id = @tabid if @indid is null begin -- Get the first unique index select top 1 @indid = i.indid from sysindexes i where (i.status & 2) <> 0 and i.id = @tabid order by i.indid asc end if @indid is null select @indid = 0 end else select @indid = 0 return @indid end go raiserror('Creating procedure sp_MSchange_priority', 0,1) GO -- @value has to be unicode too. CREATE PROCEDURE sp_MSchange_priority (@subid uniqueidentifier, @value nvarchar(255)) as update sysmergesubscriptions set priority = convert(real, @value) where subid = @subid go exec dbo.sp_MS_marksystemobject sp_MSchange_priority go grant execute on dbo.sp_MSchange_priority to public raiserror('Creating procedure sp_expired_subscription_cleanup', 0,1) GO CREATE PROCEDURE sp_expired_subscription_cleanup AS declare @retcode int declare @publisher_db sysname declare @category int declare @proc_name nvarchar(200) declare @distributor sysname declare @distribdb sysname declare @distproc nvarchar(270) /* ** 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 = sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distribdb OUTPUT IF @@ERROR <> 0 or @retcode <> 0 BEGIN RAISERROR (20036, 16, -1) return (1) END DECLARE DC CURSOR LOCAL FAST_FORWARD for select DISTINCT name, category from master..sysdatabases where (category & 4) = 4 or (category & 1 = 1) for read only open DC fetch DC into @publisher_db, @category WHILE (@@fetch_status <> -1) BEGIN if (@category & 4 = 4) begin select @proc_name = @publisher_db + '.dbo.sp_MSdrop_expired_mergesubscription' exec @retcode = @proc_name if @retcode<>0 or @@ERROR<>0 goto DONE end if (@category & 1 = 1) begin select @proc_name = @publisher_db + '.dbo.sp_MSdrop_expired_subscription' exec @retcode = @proc_name if @retcode<>0 or @@ERROR<>0 goto DONE end fetch DC into @publisher_db, @category END /* ** sp_MScleanup_agent_entry in distribution database is called to periodically remove obselete ** entries in MSmerge_agents, which may be caused by the following reasons: ** 1. publishing database is externally removed; therefore cleanup agent can not do its job ** 2. Entries for anonymous merge subscriptions */ SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '..sp_MScleanup_agent_entry' exec @retcode = @distproc if @@ERROR<>0 or @retcode<>0 BEGIN close DC deallocate DC return (1) END DONE: close DC deallocate DC GO go exec dbo.sp_MS_marksystemobject sp_expired_subscription_cleanup go grant execute on dbo.sp_expired_subscription_cleanup to public 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 @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 @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 exec dbo.sp_MS_marksystemobject sp_addmergepullsubscription go grant execute on dbo.sp_addmergepullsubscription to public go raiserror('Creating procedure sp_changemergepullsubscription', 0,1) GO CREATE PROCEDURE sp_changemergepullsubscription ( @publication sysname = '%', /* Publication name */ @publisher sysname = '%', /* Publisher server */ @publisher_db sysname = '%', /* Publication database */ @property sysname = NULL, /* The property to change */ @value nvarchar(255) = NULL /* The new property value */ ) AS SET NOCOUNT ON /* ** Declarations. */ declare @subscriber_srvid int declare @publisher_srvid int declare @retcode int declare @pubid uniqueidentifier declare @subid uniqueidentifier declare @partnerid uniqueidentifier declare @sync_typeid tinyint declare @nosync tinyint declare @automatic tinyint declare @artid uniqueidentifier declare @subscriber sysname declare @subscriber_db sysname declare @schematype int declare @schemaversion int declare @schemaguid uniqueidentifier declare @db_name sysname declare @subscriber_type int declare @schematext nvarchar(2000) /* ** Initializations. */ SET @subscriber = @@SERVERNAME SET @subscriber_db = DB_NAME() SET @nosync = 2 /* Const: synchronization type 'none' */ SET @automatic = 1 /* Const: synchronization type 'automatic' */ 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 /* ** Security Check. */ BEGIN exec @retcode = dbo.sp_MSreplcheck_subscribe if @@ERROR <> 0 or @retcode <> 0 return(1) END /* ** Check to see if current database is enabled for subscribing */ IF not exists (select name from sysobjects where name='sysmergesubscriptions') BEGIN RAISERROR (14055, 16, -1) RETURN (1) END /* ** Parameter Check: @property. ** If the @property parameter is NULL, print the options. */ IF @property IS NULL BEGIN CREATE TABLE #tab1 (properties sysname NOT NULL) INSERT INTO #tab1 VALUES ('sync_type') INSERT INTO #tab1 VALUES ('priority') INSERT INTO #tab1 VALUES ('description') select * FROM #tab1 RETURN (0) END /* ** Parameter Check: @publisher. ** Check to make sure we have a valid publisher. ** Should make sure that @publisher is non-null before using it to check whether @publication is valid */ IF @publisher IS NULL BEGIN RAISERROR (14043, 16, -1, '@publisher') 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(@publisher) and publisher_db=@publisher_db IF @pubid IS NULL BEGIN RAISERROR (20026, 11, -1, @publication) RETURN (1) END /* ** Validate that the publisher is a valid server */ select @publisher_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@publisher) IF @publisher_srvid IS NULL BEGIN RAISERROR (14010, 16, -1) RETURN (1) END /* ** Check to see if you have a local / global subscription on this publication */ set @subid = NULL select @subid = subs1.subid, @pubid = pubs.pubid, /* identified from publication name */ @subscriber_type=subs1.subscriber_type, @partnerid = subs2.subid from sysmergesubscriptions subs1, sysmergesubscriptions subs2, sysmergepublications pubs where subs1.srvid = @subscriber_srvid and subs1.db_name = @subscriber_db and subs2.srvid = @publisher_srvid and subs2.db_name = @publisher_db and subs1.pubid = subs2.subid and subs2.pubid = pubs.pubid and pubs.name = @publication and UPPER(pubs.publisher)=UPPER(@publisher) and pubs.publisher_db = @publisher_db if @subid IS NULL begin RAISERROR (14050, 11, -1) RETURN(1) end /* ** Parameter Check: @property. ** Check to make sure that @property is a valid property in ** sysarticles. */ IF LOWER(@property) NOT IN ('sync_type', 'priority', 'description') BEGIN RAISERROR (14051, 16, -1) RETURN (1) END /* ** Change the property. */ IF LOWER(@property) = 'sync_type' BEGIN /* ** Check to make sure that we have a valid sync_type. */ IF LOWER(@value) NOT IN ('automatic', 'none') BEGIN RAISERROR (14052, 16, -1) RETURN (1) END /* ** Determine the integer value for the sync_type. */ IF LOWER(@value) = 'automatic' SET @sync_typeid = @automatic ELSE SET @sync_typeid = @nosync /* ** Update the subscription with the new sync_type. */ UPDATE sysmergesubscriptions SET sync_type = @sync_typeid WHERE subid = @subid IF @@ERROR <> 0 BEGIN RAISERROR (14053, 16, -1) RETURN (1) END END IF LOWER(@property) = 'description' BEGIN UPDATE sysmergesubscriptions SET description = @value WHERE subid = @subid IF @@ERROR <> 0 BEGIN RAISERROR (14053, 16, -1) RETURN (1) END END IF LOWER(@property) = 'priority' BEGIN select @db_name = db_name from sysmergesubscriptions where (pubid=@pubid) and (subid=@pubid) IF @db_name <> db_name() BEGIN RAISERROR (20047, 16, -1) RETURN (1) END /* Only the original publisher can change priority of a global subscriptions */ IF @subscriber_type<>1 BEGIN RAISERROR (20044, 16, -1) /* Local subscriber does not have priority*/ RETURN (1) END select @schemaversion = schemaversion from sysmergeschemachange if (@schemaversion is NULL) set @schemaversion = 1 else select @schemaversion = 1 + max(schemaversion) from sysmergeschemachange set @schemaguid = newid() set @artid = newid() set @schematype = 8 /* change priority */ select @schematext = 'exec dbo.sp_MSchange_priority '+ '''' + convert(nchar(36),@subid) + '''' + ',' + '''' + @value + '''' BEGIN TRANSACTION exec dbo.sp_MSchange_priority @subid, @value exec dbo.sp_MSinsertschemachange @pubid, @artid, @schemaversion, @schemaguid, @schematype, @schematext COMMIT TRANSACTION END /* ** Return succeed. */ RAISERROR (14054, 10, -1) RETURN (0) go exec dbo.sp_MS_marksystemobject sp_changemergepullsubscription go grant execute on dbo.sp_changemergepullsubscription to public 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 @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 ) 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 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 /* exec ('declare #cursor cursor FOR select DISTINCT sub.subid, sub.partnerid ' + 'FROM sysmergesubscriptions sub, ' + 'sysmergesubscriptions sub1, ' + 'master..sysservers ss, ' + 'master..sysservers ss1, ' + 'sysmergepublications pub ' + 'WHERE ss.srvname LIKE ''' + @subscriber + '''AND UPPER(ss1.srvname) like 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 IN ' + @subscription_set + ' FOR READ ONLY') -- UNDONE 'AND sub1.subid = sub.partnerid ' */ 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 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 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 exec dbo.sp_MS_marksystemobject sp_helpmergepullsubscription go grant execute on dbo.sp_helpmergepullsubscription to public go raiserror('Creating procedure sp_addmergepullsubscription_agent', 0,1) GO CREATE PROCEDURE sp_addmergepullsubscription_agent ( @name sysname = NULL, @publisher sysname, /* Publisher server */ @publisher_db sysname, /* Publisher database */ @publication sysname, /* Publication name */ @publisher_security_mode int = 1, @publisher_login sysname = NULL, @publisher_password sysname = NULL, @publisher_encrypted_password bit = 0, @subscriber sysname = NULL, @subscriber_db sysname = NULL, @subscriber_security_mode int = NULL, /* 0 standard; 1 integrated */ @subscriber_login sysname = NULL, @subscriber_password sysname = NULL, @distributor sysname = @@SERVERNAME, @distributor_security_mode int = 1, /* 0 standard; 1 integrated */ @distributor_login sysname = NULL, @distributor_password sysname = NULL, @encrypted_password bit = 0, /* distributor password encrypted or not */ @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(255) = '', /* Optional command line arguments */ @merge_jobid binary(16) = NULL OUTPUT, @enabled_for_syncmgr nvarchar(5) = 'false', /* Enabled for SYNCMGR: true or false */ @ftp_address sysname = NULL, @ftp_port int = NULL, @ftp_login sysname = NULL, @ftp_password sysname = NULL ) AS SET NOCOUNT ON /* ** Declarations. */ declare @command nvarchar(4000) declare @retcode int declare @database sysname declare @repid uniqueidentifier declare @pubid uniqueidentifier declare @subscriber_srvid int declare @publisher_srvid int declare @name_id nvarchar(50) declare @subscriber_typeid int declare @subscription_type_id int declare @category_name sysname declare @platform_nt binary DECLARE @subscriber_enc_password sysname select @platform_nt = 0x1 -- Set null @optional_command_line to empty string to avoid string concat problem if @optional_command_line is null set @optional_command_line = '' IF @distributor_password = N'' select @distributor_password = NULL IF @publisher_password = N'' select @publisher_password = NULL IF @ftp_password = N'' select @ftp_password = NULL /* ** Parameter Check: @subscriber and @subscriber_db */ if @subscriber IS NULL or rtrim(@subscriber) = '' SELECT @subscriber = @@SERVERNAME if @subscriber_db IS NULL or rtrim(@subscriber_db) = '' SELECT @subscriber_db = DB_NAME() EXECUTE @retcode = dbo.sp_validname @subscriber IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) EXECUTE @retcode = dbo.sp_validname @subscriber_db IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) -- Parameter check: @subscriber_security_mode if @subscriber_security_mode is null begin if ( platform() & @platform_nt ) = @platform_nt select @subscriber_security_mode = 1 else select @subscriber_security_mode = 0 end if ( ( platform() & @platform_nt ) <> @platform_nt and @subscriber_security_mode = 1) begin RAISERROR(21038, 16, -1) RETURN (1) end select @subscription_type_id = 1 /* pull agent only */ /* ** Set Default schedule values if NULL is specified ** The default are not implemented during parmeter defintion because this procedure ** is can be called from sp_addmergesubscription. */ if @frequency_type is NULL set @frequency_type = 4 /* Daily */ if @frequency_interval is NULL set @frequency_interval = 1 if @frequency_relative_interval is NULL set @frequency_relative_interval = 1 if @frequency_recurrence_factor is NULL set @frequency_recurrence_factor = 0 if @frequency_subday is NULL set @frequency_subday = 8 /* Hour */ if @frequency_subday_interval is NULL set @frequency_subday_interval = 1 if @active_start_time_of_day is NULL set @active_start_time_of_day = 0 if @active_end_time_of_day is NULL set @active_end_time_of_day = 235959 if @active_start_date is NULL set @active_start_date = 0 if @active_end_date is NULL set @active_end_date = 99991231 select @subscriber_srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@@SERVERNAME) IF @subscriber_srvid IS NULL BEGIN RAISERROR (14010, 16, -1) RETURN (1) END select @pubid = pubid from sysmergepublications where name = @publication IF @pubid is NULL begin RAISERROR (14027, 16, -1, @publication) RETURN (1) end select @repid = subid, @subscriber_typeid = subscriber_type from sysmergesubscriptions where srvid = @subscriber_srvid and pubid<>subid and pubid = @pubid if @subscriber_typeid = 3 set @subscription_type_id = 2 /* This corresponds to anonymous subscription */ if (@subscription_type_id <> 0) begin if (@subscriber_security_mode = 0) and (@subscriber_login IS NULL or rtrim(@subscriber_login) = '') begin raiserror(3217, 16, -1, '@subscriber_login') return (1) end end IF NOT EXISTS (select * from sysobjects where name = 'MSsubscription_properties' and type = 'U') begin raiserror(14027, 16, -1, 'The subscription properties table ''MSsubscription_properties''') return (1) end /* ** Construct unique task name if @name = NULL */ IF @name IS NULL begin SELECT @name = CONVERT(nvarchar(23),@publisher ) + '-' + CONVERT(nvarchar(23),@publisher_db) + '-' + CONVERT(nvarchar(23),@publication) + '-' + CONVERT(nvarchar(23),@subscriber) + '-' + CONVERT(nvarchar(23), @subscriber_db) + '- 0' end else begin /* ** validate name */ exec @retcode = dbo.sp_MSreplcheck_name @name if @@ERROR <> 0 or @retcode <> 0 return(1) end /* Construct task command */ select @command = '-Publisher ' + @publisher + ' -PublisherDB ' + QUOTENAME(@publisher_db) + ' ' select @command = @command + '-Publication ' + QUOTENAME(@publication) + ' ' select @command = @command + '-Subscriber ' + QUOTENAME(@@SERVERNAME) + ' ' select @command = @command + '-SubscriberDB ' + QUOTENAME(db_name()) + ' ' SELECT @command = @command + '-SubscriptionType ' + convert(nvarchar(10), @subscription_type_id) + ' ' select @command = @command + '-SubscriberSecurityMode ' + convert(nvarchar(10),@subscriber_security_mode) + ' ' if @subscriber_login is not NULL select @command = @command + '-SubscriberLogin ' + quotename(@subscriber_login) + ' ' if @subscriber_password is not NULL begin set @subscriber_enc_password = @subscriber_password exec @retcode = master.dbo.xp_repl_encrypt @subscriber_enc_password OUTPUT select @command = @command + '-SubscriberEncryptedPassword ' + quotename(@subscriber_enc_password) + ' ' end select @command = @command + @optional_command_line select @command = @command + '-Distributor ' + @distributor + ' ' select @database = db_name() -- Get Merge category name (assumes category_id = 14) select @category_name = name FROM msdb.dbo.syscategories where category_id = 14 begin tran EXEC @retcode = dbo.sp_MSadd_repl_job @name = @name, @subsystem = 'Merge', @server = @@SERVERNAME, @databasename = @database, @enabled = 1, @freqtype = @frequency_type, @freqinterval = @frequency_interval, @freqsubtype = @frequency_subday, @freqsubinterval = @frequency_subday_interval, @freqrelativeinterval = @frequency_relative_interval, @freqrecurrencefactor = @frequency_recurrence_factor, @activestartdate = @active_start_date, @activeenddate = @active_end_date, @activestarttimeofday = @active_start_time_of_day, @activeendtimeofday = @active_end_time_of_day, @command = @command, @retryattempts = 10, @retrydelay = 1, @category_name = @category_name, @job_id = @merge_jobid OUTPUT if @@ERROR <> 0 or @retcode <> 0 begin goto undo end if (@subscription_type_id = 1) OR (@subscription_type_id = 2) begin IF NOT EXISTS (select * from MSsubscription_properties where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication) BEGIN IF (@encrypted_password = 0) -- Encrypt the password BEGIN EXEC @retcode = master.dbo.xp_repl_encrypt @distributor_password OUTPUT IF @@error <> 0 OR @retcode <> 0 return 1 END IF (@publisher_encrypted_password = 0) -- Encrypt the password BEGIN EXEC @retcode = master.dbo.xp_repl_encrypt @publisher_password OUTPUT IF @@error <> 0 OR @retcode <> 0 return 1 END INSERT INTO MSsubscription_properties (publisher, publisher_db, publication, publication_type, publisher_login,publisher_password, publisher_security_mode, distributor, distributor_login, distributor_password, distributor_security_mode, ftp_address, ftp_port, ftp_login, ftp_password) values (@publisher, @publisher_db, @publication, 2, @publisher_login, @publisher_password, @publisher_security_mode, @distributor, @distributor_login, @distributor_password, @distributor_security_mode, @ftp_address, @ftp_port, @ftp_login, @ftp_password) IF @@ERROR <> 0 BEGIN IF @@TRANCOUNT = 1 ROLLBACK TRAN ELSE COMMIT TRAN RETURN(1) END END end /* Update merge joibd for this pull subscription */ UPDATE MSmerge_replinfo set merge_jobid = @merge_jobid WHERE repid = @repid /* Conditional support for MobileSync */ if LOWER(@enabled_for_syncmgr) = 'true' BEGIN /* Call sp_MSregistersubscription so that the subscription can be synchronized via MobileSync etc. */ exec @retcode = dbo.sp_MSregistersubscription @replication_type = 2, @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @subscriber = @subscriber, @subscriber_db = @subscriber_db, @subscriber_security_mode = @subscriber_security_mode, @subscriber_login = @subscriber_login, @subscriber_password = @subscriber_password, @distributor = @distributor, @subscription_id = @repid, @subscription_type = @subscription_type_id IF @@ERROR <> 0 or @retcode <> 0 BEGIN goto undo END END commit tran RETURN (0) undo: IF @@TRANCOUNT = 1 ROLLBACK TRAN ELSE COMMIT TRAN GO exec dbo.sp_MS_marksystemobject sp_addmergepullsubscription_agent go raiserror('Creating procedure sp_MSget_mergepullsubsagent_owner', 0,1) GO CREATE PROCEDURE sp_MSget_mergepullsubsagent_owner( @publication sysname = NULL, /* Publication name */ @publisher sysname = NULL, /* Publisher server */ @publisher_db sysname = NULL, /* Publication database */ @owner_sid varbinary(85) OUTPUT )AS declare @srvid int declare @pubid uniqueidentifier declare @subid uniqueidentifier declare @job_id uniqueidentifier set nocount on select @owner_sid = NULL if exists (select * from sysobjects where type = 'U' and name = 'sysmergesubscriptions') -- Get the server id of the current server (subscriber) begin -- Get the srvid of the current subscriber database select @srvid = srvid from master.dbo.sysservers where upper(@@servername) = upper(srvname) -- Get the pubid from sysmergepublications using @publisher, -- @publisher_db, @publication select @pubid = pubid from sysmergepublications where @publication = name -- Get the subid from sysmergesubscriptions using @pubid and @srvid select @subid = subid from sysmergesubscriptions where @pubid = pubid and @srvid = srvid and pubid <> subid -- Get the merge_jobid from MSreplication_info using @subid select @job_id = merge_jobid from MSmerge_replinfo where @subid = repid -- Finally, get the owner_sid from msdb..sysjobs using @job_id select @owner_sid = owner_sid from msdb..sysjobs where @job_id = job_id end go exec dbo.sp_MS_marksystemobject 'sp_MSget_mergepullsubsagent_owner' 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 IF (@subscriber_type<>1) begin DELETE MSmerge_replinfo WHERE repid = @subid IF @@ERROR <> 0 GOTO FAILURE delete from sysmergesubscriptions where subid = @subid if @@ERROR <> 0 GOTO FAILURE end ELSE update sysmergesubscriptions set status = 2 where subid =@subid /* 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 exec dbo.sp_MS_marksystemobject sp_dropmergepullsubscription go grant execute on dbo.sp_dropmergepullsubscription to public go -- synctran supporting sprocs 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) go raiserror('Creating procedure sp_check_sync_trigger', 0,1) go create proc sp_check_sync_trigger @trigger_procid int, @trigger_op char(10) OUTPUT as select @trigger_op = NULL -- debug -- select 'Entered sp_check_synctrigger', 'calling trigger' = object_name(@trigger_procid) -- debug declare @trigid int select @trigid = so1.id from sysobjects so1, sysobjects so2 where so1.type = N'TR' and so1.name like N'trg_MSsync_ins_%' and so1.parent_obj = so2.parent_obj and so2.id = @trigger_procid -- if nestlevel of insert trigger on same table > 0 then bail if trigger_nestlevel( @trigid ) > 0 begin -- debug -- select 'sp_check_synctrigger: synctran insert trigger is active, so do nothing' -- debug return 1 end else return 0 go raiserror('Creating procedure sp_check_for_sync_trigger', 0,1) go create proc sp_check_for_sync_trigger @tabid int, @trigger_op char(10) = NULL OUTPUT as select @trigger_op = NULL -- debug -- select 'Entered sp_check_for_sync_trigger', 'calling trigger' = object_name(@trigger_procid) -- debug declare @ins_trigid int declare @upd_trigid int declare @del_trigid int select @ins_trigid = id from sysobjects where type = N'TR' and name like N'trg_MSsync_ins_%' and parent_obj = @tabid select @upd_trigid = id from sysobjects where type = N'TR' and name like N'trg_MSsync_upd_%' and parent_obj = @tabid select @del_trigid = id from sysobjects where type = N'TR' and name like N'trg_MSsync_del_%' and parent_obj = @tabid if trigger_nestlevel( @ins_trigid ) > 0 begin -- debug -- select 'sp_check_for_sync_trigger: synctran insert trigger is active' -- debug select @trigger_op = 'ins' return 1 end else -- if nestlevel of insert trigger on same table > 0 then bail if trigger_nestlevel( @upd_trigid ) > 0 begin -- debug -- select 'sp_check_for_sync_trigger: synctran update trigger is active' -- debug select @trigger_op = 'upd' return 1 end else if trigger_nestlevel( @del_trigid ) > 0 begin -- debug -- select 'sp_check_for_sync_trigger: synctran update trigger is active' -- debug select @trigger_op = 'del' return 1 end else return 0 go raiserror('Creating procedure sp_MSpad_command', 0,1) go create proc sp_MSpad_command @cmd nvarchar(4000) output, @indent int = 0 -- indent for command buffer (for pretty formatting as declare @cnt int select @cmd = N'' select @cnt = 0 while (@cnt < @indent) begin select @cmd = @cmd + N' ' select @cnt = @cnt + 1 end go raiserror('Creating procedure sp_MSflush_command', 0,1) go create proc sp_MSflush_command @cmd nvarchar(4000) output, @force int, -- 0 = flush if necesssary, 1 = flush always @indent int = 0 -- indent for command buffer (for pretty formatting as -- debug -- if len(@cmd) >= 4000 -- begin -- raiserror("buffer overflow!", 16, 1) -- select @cmd -- end -- debug if @force = 1 or len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' if @indent > 0 exec dbo.sp_MSpad_command @cmd output, @indent end go raiserror('Creating procedure sp_MSget_colinfo', 0,1) go create proc sp_MSget_colinfo @objid int, @colid int, @columns binary(32), @bGetTextImageInfo tinyint = 0, -- boolean for returning text/image info @colname sysname output, @ccoltype sysname output as declare @isset int if @columns is not NULL -- this code path for synctran procs exec @isset = dbo.sp_isarticlecolbitset @colid, @columns else -- this code path for synctran triggers select @isset = 1 if @isset != 0 begin select @colname = c.name, @ccoltype= t.name from syscolumns c, systypes t where id = @objid and colid = @colid and c.xtype = t.xusertype -- when checking replicated columns, text/image datatypes cannot be declared or used locally if (@bGetTextImageInfo = 0) and (@ccoltype in (N'text',N'ntext',N'image')) return 1 end else begin select @colname = null, @ccoltype = null return 1 end return 0 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, 0, @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 raiserror('Creating procedure sp_MSget_type', 0,1) go create proc sp_MSget_type @tabid int, @colid int, @colname sysname output, @typestring nvarchar(4000) output as declare @ccolchar nvarchar(5) declare @coltype tinyint declare @prec smallint declare @scale int declare @ccoltype sysname declare @xtype int select @colname = c.name, @xtype = c.xtype, @prec = c.prec, @scale = c.scale, @ccoltype = t.name from syscolumns c, systypes t where c.id = @tabid and c.colid = @colid and c.xtype = t.xusertype select @typestring = @ccoltype -- datatypes requiring precision (nchar, nvarchar, binary, varbinary) -- format: @var
(prec) if @ccoltype in (N'char',N'nchar', N'varchar', N'nvarchar', N'binary', N'varbinary') select @typestring = @typestring + N'(' + rtrim(convert(nchar(10),@prec)) + N')' -- datatypes requiring precision & scale (numeric & decimal) -- format: @var
(prec, scale) else if @ccoltype in (N'numeric', N'decimal') select @typestring = @typestring + N'(' + rtrim(convert(nchar(10),ColumnProperty(@tabid, @colname, 'PRECISION'))) + N',' + rtrim(convert(nchar(10),@scale)) + N')' -- text/image datatypes cannot be declared or used locally else if @ccoltype in (N'text',N'ntext',N'image') select @typestring = NULL 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 if @clause_type = 'new pk' begin if ColumnProperty(@objid, @key, 'IsIdentity') = 1 select @cmd = @cmd + @spacer + @key + N' = @@identity' else select @cmd = @cmd + @spacer + @key + N' = @' + @col select @spacer = ' and ' end else if @clause_type = 'upd ts' begin select @cmd = @cmd + @spacer + @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 + @key + N' = @' + @col + N'_old' else -- The vars correspoding to pk were set in sp_MSscript -- _pkvar_assignment. select @cmd = @cmd + @spacer + @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 raiserror('Creating procedure sp_MSscript_params', 0,1) go create procedure sp_MSscript_params @objid int, @columns binary(32), @postfix nvarchar(8) = NULL, @bOutParams tinyint = 0, -- boolean indicating wether or not to declare timestamp/identity params as output params @outvars nvarchar(4000) = NULL output as declare @cmd nvarchar(4000) declare @colname sysname declare @typestring nvarchar(4000) declare @spacer nvarchar(1) declare @spacer2 nvarchar(1) declare @src_cols int declare @this_col int declare @art_col int declare @isset int select @spacer = N' ' select @spacer2 = N' ' select @this_col = 1 select @art_col = 1 select @src_cols = count(*) from syscolumns where id = @objid select @outvars = null select @cmd = N'' while @this_col <= @src_cols begin if @columns is not null exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns else select @isset = 1 if @isset != 0 and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1) begin exec dbo.sp_MSget_type @objid, @this_col, @colname output, @typestring OUTPUT if @typestring != NULL begin if @postfix is null select @cmd = @cmd + @spacer + N'@c' + convert(varchar(4), @this_col) + N' ' + @typestring else -- old vars select @cmd = @cmd + @spacer + N'@c' + convert(varchar(4), @this_col) + @postfix + N' ' + @typestring -- new vars of type timestamp and identity are declared as output params if @bOutParams = 1 and (@typestring = N'timestamp' or ColumnProperty(@objid, @colname, 'IsIdentity') = 1) begin select @cmd = @cmd + N' output' select @outvars = isnull(@outvars, N'') + @spacer2 + N'@c' + convert(varchar(4), @this_col) + N' = ' + @colname select @spacer2 = N',' end select @spacer = N',' end select @art_col = @art_col + 1 -- flush command if necessary exec dbo.sp_MSflush_command @cmd output, 0 end select @this_col = @this_col + 1 end -- save off cmd fragment exec dbo.sp_MSflush_command @cmd output, 1 go raiserror('Creating procedure sp_MSscript_begintrig1', 0,1) go create procedure sp_MSscript_begintrig1 @trigname sysname, @objid int, @procname sysname, @filter_clause nvarchar(4000), @op_type char(3) = 'ins' -- ins, upd, del as declare @cmd nvarchar(4000) declare @start int declare @sub_len int declare @qualname nvarchar(512) exec sp_MSget_qualified_name @objid, @qualname OUTPUT -- construct trigger name select @cmd = N'create trigger ' + QUOTENAME(@trigname) + N' on ' + @qualname + N' ' if @op_type = 'ins' select @cmd = @cmd + N'for insert not for replication as ' else if @op_type = 'upd' select @cmd = @cmd + N'for update not for replication as ' else if @op_type = 'del' select @cmd = @cmd + N'for delete not for replication as ' exec dbo.sp_MSflush_command @cmd output, 1 -- declare common local variables insert into #proctext(procedure_text) values (N'declare @rc int, @retcode int, @connect_string nvarchar(2000), @rpc_proc nvarchar(4000), ') insert into #proctext(procedure_text) values (N'@rpc_types nvarchar(4000), @bitmap varbinary(4000) ') -- script variables used to retrieve data from inserted table if @op_type in ('ins', 'upd') begin insert into #proctext(procedure_text) values(N'declare ') exec dbo.sp_MSscript_params @objid, null, null, 0, null insert into #proctext(procedure_text) values(N' ') end insert into #proctext(procedure_text) values(N'declare ') exec dbo.sp_MSscript_params @objid, null, '_old', 0, null insert into #proctext(procedure_text) values(N' ') insert into #proctext(procedure_text) values(N'select @rc = @@ROWCOUNT ') -- Optimization. Return immediately if no row changed -- This must be at the beginning of the trigger to @@rowcount be overwritten. insert into #proctext(procedure_text) values(N'if @rc = 0 return ') insert into #proctext(procedure_text) values(N'select @bitmap = columns_updated() ') -- Partition check statement if @filter_clause IS NOT NULL begin insert into #proctext(procedure_text) values (N'if exists (select * from inserted where not (') -- break filter_clause into chunks of 255 select @start = 1 while @start < len(@filter_clause) begin if len(@filter_clause) < 255 select @sub_len = len(@filter_clause) else select @sub_len = 255 select @cmd = substring(@filter_clause, @start, @sub_len) exec dbo.sp_MSflush_command @cmd output, 1 select @start = @start + @sub_len end insert into #proctext(procedure_text) values (N')) begin exec sp_MSreplraiserror 21034 goto FAILURE end ') end go raiserror('Creating procedure sp_MSscript_begintrig2', 0,1) go create procedure sp_MSscript_begintrig2 @objid int, @op_type char(3) = 'ins' -- ins, upd, del as declare @cmd nvarchar(4000) --select @cmd = N'if Objectproperty(@@procid, ' if @op_type = 'ins' insert into #proctext(procedure_text) values(N'if Objectproperty(@@procid,''TriggerInsertOrder'') != 1 begin raiserror (21128, 16, 1) return end ') else if @op_type = 'upd' insert into #proctext(procedure_text) values(N'if Objectproperty(@@procid,''TriggerUpdate'') != 1 begin raiserror (21129, 16, 1) return end ') else if @op_type = 'del' insert into #proctext(procedure_text) values(N'if Objectproperty(@@procid,''TriggerDeleteOrder'') != 1 begin raiserror (21130, 16, 1) return end ') -- debug -- insert into #proctext(procedure_text) values(N' ') -- if @op_type = 'ins' -- insert into #proctext(procedure_text) -- values(N'select ''SyncTran Insert Trigger fired on table'' = ' + N'''' + @source_table + N'''') -- else if @op_type = 'upd' -- insert into #proctext(procedure_text) -- values(N'select ''SyncTran Update Trigger fired on table'' = ' + N'''' + @source_table + N'''') -- else if @op_type = 'del' -- insert into #proctext(procedure_text) -- values(N'select ''SyncTran Delete Trigger fired on table'' = ' + N'''' + @source_table + N'''') -- insert into #proctext(procedure_text) values(N' , ''global nestlevel'' = trigger_nestlevel() ') -- insert into #proctext(procedure_text) values(N' , ''local nestlevel'' = trigger_nestlevel(@@procid) ') -- if @op_type = 'ins' -- insert into #proctext(procedure_text) values(N' , ''fire_order'' = Objectproperty(@@procid, ''TriggerInsertOrder'') ') -- if @op_type = 'upd' -- insert into #proctext(procedure_text) values(N' , ''fire_order'' = Objectproperty(@@procid, ''TriggerUpdateOrder'') ') -- if @op_type = 'del' -- insert into #proctext(procedure_text) values(N' , ''fire_order'' = Objectproperty(@@procid, ''TriggerDeleteOrder'') ') -- debug -- Get rpc prefix -- Get rpc prefix insert into #proctext(procedure_text) values (N'exec @retcode = dbo.sp_MSget_publisher_rpc @@procid, @connect_string output if @retcode <>0 or @@error <> 0 goto FAILURE ') insert into #proctext(procedure_text) values(N'BEGIN DISTRIBUTED TRAN ') go raiserror('Creating procedure sp_MSscript_endtrig', 0,1) go create proc sp_MSscript_endtrig as declare @cmd nvarchar(4000) insert into #proctext(procedure_text) values(N'if @@trancount > 0 commit tran return ') insert into #proctext(procedure_text) values(N'FAILURE: if @@trancount > 0 begin exec sp_MSreplraiserror 20512 rollback tran end ') go raiserror('Creating procedure sp_MSscript_trigger_variables', 0,1) go create procedure sp_MSscript_trigger_variables @objid int, @prefix char(1) = null, -- null or '@' @postfix varchar(4) = null, @indent int = 0, @spacer nvarchar(1) = N' ', @bOutput_params tinyint = 0, -- declare output params if necessary @identity_col sysname = null, @ts_col sysname = null, @include_type bit = 0, @set_nulls bit = 0, @op_type char(3) = 'ins', -- 'ins, 'upd', 'del' @is_new bit = 0, @primary_key_bitmap varbinary(4000) = NULL as declare @cmd nvarchar(4000) declare @colname sysname declare @ccoltype sysname declare @src_cols int declare @this_col int declare @art_col int declare @rc int declare @column nvarchar(4000) select @cmd = N'' -- script cursor select variables 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, 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 @prefix is null begin if (@set_nulls = 1) begin -- Optimization: -- Get null or actual column name -- Note: the output is quoted. exec dbo.sp_MSget_synctran_column @ts_col, @op_type, -- 'ins, 'upd', 'del' @is_new, @primary_key_bitmap, @colname, @this_col, @column output, 0, @ccoltype select @cmd = @cmd + @spacer + @column + isnull(@postfix, N'') end else select @cmd = @cmd + @spacer + N'[' + @colname + isnull(@postfix, N'') + N']' end else select @cmd = @cmd + @spacer + isnull(@prefix, N'') + N'c' + RTRIM(convert(nvarchar(4), @this_col)) + isnull(@postfix, N'') if @include_type = 1 begin declare @typestring nvarchar(100) exec dbo.sp_MSget_type @objid, @this_col, @colname output, @typestring OUTPUT select @cmd = @cmd + N' ' + @typestring end -- new vars of type timestamp and identity are declared as output params if (@bOutput_params = 1 and (@ccoltype = N'timestamp' or ColumnProperty(@objid, @colname, 'IsIdentity') = 1)) or (@colname = @identity_col or @colname = @ts_col) begin -- YWU: Do this to avoid output in cursor declaration statement. -- The right thing seems to be set output only when bOutput_params is set -- but it seems not the way this sp is called. if @set_nulls = 0 select @cmd = @cmd + N' output' end select @spacer = N',' end exec dbo.sp_MSflush_command @cmd output, 0, @indent select @this_col = @this_col + 1 end exec dbo.sp_MSflush_command @cmd output, 1, @indent insert into #proctext(procedure_text) values(N' ') go raiserror('Creating procedure sp_MSscript_trigger_assignment', 0,1) go create procedure sp_MSscript_trigger_assignment @objid int, @postfix char(4) = null, @indent int = 0, @ts_col sysname, @op_type char(3), -- 'ins, 'upd', 'del' @is_new bit, @primary_key_bitmap varbinary(4000) as declare @cmd nvarchar(4000) declare @colname sysname declare @spacer nvarchar(1) declare @ccoltype sysname declare @src_cols int declare @this_col int declare @art_col int declare @rc int declare @column nvarchar(4000) -- script cursor select variables select @src_cols = count(*) from syscolumns where id = @objid select @spacer = N' ' 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, 0, @colname output, @ccoltype output if @rc = 0 and EXISTS (select name from syscolumns where id=@objid and @this_col=colid and iscomputed<>1) begin -- Optimization: -- Get null or actual column name -- Note: the output is quoted. exec dbo.sp_MSget_synctran_column @ts_col, @op_type, -- 'ins, 'upd', 'del' @is_new, @primary_key_bitmap, @colname, @this_col, @column output select @cmd = @cmd + @spacer + N'@c' + convert(varchar(4), @this_col) + isnull(@postfix, N'') + N' = ' + @column select @spacer = N',' end exec dbo.sp_MSflush_command @cmd output, 0, @indent select @this_col = @this_col + 1 end exec dbo.sp_MSflush_command @cmd output, 1, @indent insert into #proctext(procedure_text) values(N' ') go raiserror('Creating procedure sp_MSscript_trigger_fetch_statement', 0,1) go create procedure sp_MSscript_trigger_fetch_statement @objid int, @op_type char(3) = 'ins', @indent int = 0 as declare @cmd nvarchar(4000) exec dbo.sp_MSpad_command @cmd output, @indent -- script fetch statements if @op_type in ('ins', 'upd') begin exec dbo.sp_MSpad_command @cmd output, @indent select @cmd = @cmd + (N'fetch next from rpl_ins_cursor into ') exec dbo.sp_MSflush_command @cmd output, 1, @indent exec dbo.sp_MSscript_trigger_variables @objid, '@', null, @indent, ' ' end if @op_type in ('ins') begin exec dbo.sp_MSpad_command @cmd output, @indent select @cmd = @cmd + (N'fetch next from rpl_ins2_cursor into ') exec dbo.sp_MSflush_command @cmd output, 1, @indent exec dbo.sp_MSscript_trigger_variables @objid, '@', '_old', @indent, ' ' end if @op_type in ('upd', 'del') begin exec dbo.sp_MSpad_command @cmd output, @indent select @cmd = @cmd + (N'fetch next from rpl_del_cursor into ') exec dbo.sp_MSflush_command @cmd output, 1, @indent exec dbo.sp_MSscript_trigger_variables @objid, '@', '_old', @indent, ' ' end go raiserror('Creating procedure sp_MSscript_trigger_exec_rpc ', 0,1) go create procedure sp_MSscript_trigger_exec_rpc @publisher sysname, @publisherdb sysname, @procname sysname, @proc_owner sysname, @objid int, @op_type char(3) = 'ins', @indent int = 0, @identity_col sysname = null, @ts_col sysname = null as declare @cmd nvarchar(4000) declare @min_identity int declare @max_identity int insert into #proctext(procedure_text) values (N' if @connect_string is null begin ') select @cmd = N' exec @retcode = ' + quotename(@publisher) + N'.' + quotename(@publisherdb) + N'.' + quotename(@proc_owner) + N'.' + quotename(@procname) -- 1st two variables are subscriber server name and database name for cycle detection select @cmd = @cmd + ' ' + quotename(@@SERVERNAME) + N', ' + quotename(db_name()) + N', ' exec dbo.sp_MSflush_command @cmd, 1, @indent select @min_identity = @@identity if @op_type in ('ins', 'upd') exec dbo.sp_MSscript_trigger_variables @objid, '@', N'', @indent, N'', 0, @identity_col, @ts_col if @op_type = 'upd' begin exec dbo.sp_MSscript_trigger_variables @objid, '@', '_old', @indent, ',', 0, null, null insert into #proctext(procedure_text) values (N', @bitmap') end else if @op_type = 'del' exec dbo.sp_MSscript_trigger_variables @objid, '@', '_old', @indent, ' ', 0, null, null select @max_identity = @@identity -- Raise friendly error. insert into #proctext(procedure_text) values (N' if @@error <>0 or @retcode <> 0 begin exec sp_MSreplraiserror 21054 goto FAILURE end ') -- End if @connect is null insert into #proctext(procedure_text) values (N' end else begin ') select @cmd = ' select @rpc_proc = N''declare @retcode int exec @retcode = '' + N' select @cmd = @cmd + quotename('OpenDataSource(''SQLOLEDB'',N' ,'''') select @cmd = @cmd + '+ '''''''' + replace(@connect_string, '''''''', '''''''''''''''') + N'''''''' + ' select @cmd = @cmd + 'N'').'' + N''' select @cmd = @cmd + quotename(@publisherdb) + '.' select @cmd = @cmd + quotename(@proc_owner) + '.' select @cmd = @cmd + quotename(@procname) + ''' + N' select @cmd = @cmd + quotename(quotename(@@SERVERNAME),'''') + ' + '','' + N' select @cmd = @cmd + quotename(quotename(db_name()),'''') + ' + '','' + '' ' exec dbo.sp_MSflush_command @cmd, 1, @indent -- Get parameters if @op_type in ('ins', 'upd') exec dbo.sp_MSscript_trigger_variables @objid, '@', N'', @indent, N'', 0, @identity_col, @ts_col if @op_type = 'upd' begin exec dbo.sp_MSscript_trigger_variables @objid, '@', 'o', @indent, ',', 0, null, null insert into #proctext(procedure_text) values (N', @bitmap') end else if @op_type = 'del' exec dbo.sp_MSscript_trigger_variables @objid, '@', 'o', @indent, ' ', 0, null, null -- Must raise error right before exiting the dynamic exec so that it will be picked up. insert into #proctext(procedure_text) values (N' '' + '' if @@error <>0 or @retcode <> 0 exec sp_MSreplraiserror 21054'' ') -- Get parameter datatypes insert into #proctext(procedure_text) values (N' select @rpc_types = ''') if @op_type in ('ins', 'upd') exec dbo.sp_MSscript_trigger_variables @objid, '@', N'' , @indent, N'', 0, @identity_col, @ts_col, 1 if @op_type = 'upd' exec dbo.sp_MSscript_trigger_variables @objid, '@', 'o', @indent, ',', 0, null, null, 1 else if @op_type = 'del' exec dbo.sp_MSscript_trigger_variables @objid, '@', 'o', @indent, ' ', 0, null, null, 1 insert into #proctext(procedure_text) values (N' ''') if @op_type = 'upd' begin insert into #proctext(procedure_text) values (N' select @rpc_types = @rpc_types + '', @bitmap varbinary(4000)'' ') end -- make rpc call insert into #proctext(procedure_text) values (N' exec @retcode = dbo.sp_executesql @rpc_proc, @rpc_types, ') -- Get parameters again insert into #proctext(procedure_text) select procedure_text from #proctext where c1 > @min_identity and c1 <= @max_identity order by c1 asc insert into #proctext(procedure_text) values (N' if @@error <>0 goto FAILURE ') -- end else insert into #proctext(procedure_text) values (N' end ') 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(' + @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(' + @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(' + @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(' + @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 raiserror('Creating procedure sp_MSscript_trigger_updates', 0,1) go create procedure sp_MSscript_trigger_updates @identity_col sysname, @ts_col sysname, @op_type char(3) = 'ins', -- 'ins', 'del' @objid int, @indent int = 0 as declare @cmd nvarchar(4000) declare @col sysname declare @qualname nvarchar(512) if @op_type = 'upd' begin -- Script out pk var assigment that used in sp_MSscript_where_clause exec dbo.sp_MSscript_pkvar_assignment @objid, NULL, 1, @identity_col, @ts_col insert into #proctext(procedure_text) values(N' ') end exec sp_MSget_qualified_name @objid, @qualname OUTPUT if @ts_col is not null begin insert into #proctext(procedure_text) values(N' ') exec dbo.sp_MSpad_command @cmd output, @indent exec dbo.sp_MSget_col_position @objid, null, @ts_col, @col output select @cmd = @cmd + N'update ' + @qualname + N' set ' + @ts_col + N' = @' + @col exec dbo.sp_MSflush_command @cmd, 1 exec dbo.sp_MSscript_where_clause @objid, null, 'trg pk', null, @indent, @op_type end if @op_type = 'ins' and @identity_col is not null begin insert into #proctext(procedure_text) values(N' ') exec dbo.sp_MSpad_command @cmd output, @indent exec dbo.sp_MSget_col_position @objid, null, @identity_col, @col output select @cmd = @cmd + N'update ' + @qualname + N' set ' + @identity_col + N' = @' + @col exec dbo.sp_MSflush_command @cmd, 1 exec dbo.sp_MSscript_where_clause @objid, null, 'trg pk', null, @indent, @op_type end go raiserror('Creating procedure sp_MSscript_singlerow_trigger', 0,1) go create procedure sp_MSscript_singlerow_trigger @objid int, @publisher sysname, @publisher_db sysname, @procname sysname, @proc_owner sysname, @identity_col sysname, @ts_col sysname, @op_type char(3) = 'ins', -- 'ins, 'upd', 'del' @primary_key_bitmap varbinary(4000) = NULL as declare @colname sysname declare @spacer nvarchar(1) declare @ccoltype sysname declare @src_cols int declare @this_col int declare @rc int select @src_cols = count(*) from syscolumns where id = @objid if @op_type in ('ins', 'upd') exec dbo.sp_MSscript_trigger_update_checks @objid, @identity_col, @ts_col, @op_type, 0 insert into #proctext(procedure_text) values(N'if @rc = 1 begin ') if @op_type in ('ins', 'upd') begin insert into #proctext(procedure_text) values(N' select') exec dbo.sp_MSscript_trigger_assignment @objid, null, 4, @ts_col, @op_type, 1, @primary_key_bitmap insert into #proctext(procedure_text) values(N' from inserted ') end if @op_type in ('ins') begin insert into #proctext(procedure_text) values(N' select') exec dbo.sp_MSscript_trigger_assignment @objid, '_old', 4, @ts_col, @op_type, 0, @primary_key_bitmap insert into #proctext(procedure_text) values(N' from inserted ') end else if @op_type in ('upd', 'del') begin insert into #proctext(procedure_text) values(N' select') exec dbo.sp_MSscript_trigger_assignment @objid, '_old', 4, @ts_col, @op_type, 0, @primary_key_bitmap insert into #proctext(procedure_text) values(N' from deleted ') end exec dbo.sp_MSscript_trigger_exec_rpc @publisher, @publisher_db, @procname, @proc_owner, @objid, @op_type, 12, @identity_col, @ts_col if @op_type in ('ins', 'upd') exec dbo.sp_MSscript_trigger_updates @identity_col, @ts_col, @op_type, @objid, 4 insert into #proctext(procedure_text) values(N'end ') go raiserror('Creating procedure sp_MSscript_multirow_trigger', 0,1) go create procedure sp_MSscript_multirow_trigger @objid int, @publisher sysname, @publisher_db sysname, @procname sysname, @proc_owner sysname, @identity_col sysname, @ts_col sysname, @op_type char(3) = 'ins', -- 'ins, 'upd', 'del' @primary_key_bitmap varbinary(4000) = NULL as declare @cmd nvarchar(4000) insert into #proctext(procedure_text) values(N'else begin ') -- setup cursor over inserted table for ins & upd triggers if @op_type in ('ins', 'upd') begin insert into #proctext(procedure_text) values(N' declare rpl_ins_cursor CURSOR LOCAL FAST_FORWARD FOR select ') exec dbo.sp_MSscript_trigger_variables @objid, null, null, 4, ' ', 0,@identity_col, @ts_col,0, 1, @op_type, 1, @primary_key_bitmap insert into #proctext(procedure_text) values(N' from inserted for read only ') insert into #proctext(procedure_text) values(N' open rpl_ins_cursor ') end if @op_type in ('ins') begin insert into #proctext(procedure_text) values(N' declare rpl_ins2_cursor CURSOR LOCAL FAST_FORWARD FOR select ') exec dbo.sp_MSscript_trigger_variables @objid, null, null, 4, ' ' insert into #proctext(procedure_text) values(N' from inserted for read only ') insert into #proctext(procedure_text) values(N' open rpl_ins2_cursor ') end -- setup cursor over deleted table for upd & del triggers if @op_type in ('upd', 'del') begin insert into #proctext(procedure_text) values(N' declare rpl_del_cursor CURSOR LOCAL FAST_FORWARD FOR select ') exec dbo.sp_MSscript_trigger_variables @objid, null, null, 4, ' ', 0,@identity_col, @ts_col,0, 1, @op_type, 0, @primary_key_bitmap insert into #proctext(procedure_text) values(N' from deleted for read only ') insert into #proctext(procedure_text) values(N' open rpl_del_cursor ') end -- script fetch statement exec dbo.sp_MSscript_trigger_fetch_statement @objid, @op_type, 4 insert into #proctext(procedure_text) values(N' ') insert into #proctext(procedure_text) values(N' while @@fetch_status <> -1 begin ') exec dbo.sp_MSscript_trigger_exec_rpc @publisher, @publisher_db, @procname, @proc_owner, @objid, @op_type, 16, @identity_col, @ts_col if @op_type in ('ins', 'upd') exec dbo.sp_MSscript_trigger_updates @identity_col, @ts_col, @op_type, @objid, 8 exec dbo.sp_MSscript_trigger_fetch_statement @objid, @op_type, 8 insert into #proctext(procedure_text) values(N' end ') if @op_type in ('ins', 'upd') begin insert into #proctext(procedure_text) values(N' close rpl_ins_cursor deallocate rpl_ins_cursor ') end if @op_type in ('upd', 'del') begin insert into #proctext(procedure_text) values(N' close rpl_del_cursor deallocate rpl_del_cursor ') end insert into #proctext(procedure_text) values(N'end ') go go raiserror('Creating procedure sp_MSscript_sync_ins_trig', 0,1) go create procedure sp_MSscript_sync_ins_trig @objid int, @publisher sysname, @publisher_db sysname, @trigname sysname, @procname sysname, @proc_owner sysname, @identity_col sysname = NULL, @ts_col sysname = NULL, @filter_clause nvarchar(4000) as 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 declare @qualname nvarchar(512) set nocount on exec sp_MSget_qualified_name @objid, @qualname OUTPUT if @ts_col in ('null','NULL') select @ts_col = null if @identity_col in ('null','NULL') select @identity_col = null if @ts_col is null begin -- row compare method only supports updates select N'create trigger ' + QUOTENAME(@trigname) + N' on ' + @qualname + N' for insert not for replication ' + N'as ' + N' exec sp_MSreplraiserror 20518 ' + N' rollback transaction ' end else begin -- Can't insert table with timestamp or identity col if no unique index exec @indid = dbo.sp_MStable_has_unique_index @objid if (@ts_col is not null or @identity_col is not null) and @indid = 0 begin select N'create trigger ' + QUOTENAME(@trigname) + N' on ' + @qualname + N' for insert not for replication ' + N'as ' + N' exec sp_MSreplraiserror 20519 ' + N' rollback transaction ' end else begin -- Create temp table create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL) -- 1st preamble common to all synctran procs exec dbo.sp_MSscript_begintrig1 @trigname, @objid, @procname, @filter_clause, 'ins' -- 2nd preamble common to all synctran procs exec dbo.sp_MSscript_begintrig2 @objid, 'ins' -- script single row handling exec @rc = dbo.sp_MSscript_singlerow_trigger @objid,@publisher, @publisher_db, @procname, @proc_owner, @identity_col, @ts_col, 'ins' -- script multi-row handling exec @rc = dbo.sp_MSscript_multirow_trigger @objid, @publisher, @publisher_db, @procname, @proc_owner, @identity_col, @ts_col, 'ins' -- script end of trigger exec dbo.sp_MSscript_endtrig -- send fragments to client select procedure_text from #proctext order by c1 asc end end go raiserror('Creating procedure sp_MSscript_sync_upd_trig', 0,1) go create procedure sp_MSscript_sync_upd_trig @objid int, @publisher sysname, @publisher_db sysname, @trigname sysname, @procname sysname, @proc_owner sysname, @identity_col sysname = NULL, @ts_col sysname = NULL, @filter_clause nvarchar(4000), @primary_key_bitmap varbinary(4000) as 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 declare @qualname nvarchar(512) set nocount on exec sp_MSget_qualified_name @objid, @qualname OUTPUT if @ts_col in ('null','NULL') select @ts_col = null if @identity_col in ('null','NULL') select @identity_col = null exec @indid = dbo.sp_MStable_has_unique_index @objid if @ts_col is not null and @indid = 0 begin select N'create trigger ' + QUOTENAME(@trigname) + N' on ' + @qualname + N' for update not for replication ' + N'as ' + N' exec sp_MSreplraiserror 20520 ' + N' rollback transaction ' end else begin -- Create temp table create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL) -- 1st preamble common to all synctran procs exec dbo.sp_MSscript_begintrig1 @trigname, @objid, @procname, @filter_clause, 'upd' -- trigger nesting checks insert into #proctext(procedure_text) values(N' ') insert into #proctext(procedure_text) values(N'declare @trigger_op char(10) ') insert into #proctext(procedure_text) values(N'exec @retcode = dbo.sp_check_sync_trigger @@procid, @trigger_op OUTPUT ') insert into #proctext(procedure_text) values(N'if @retcode = 1 return ' ) -- prevent updating of unique index when 'row compare' conflict detection, since it would trickle -- back as a del/insert, and fail if @ts_col is null begin insert into #proctext(procedure_text) values(N' ') exec dbo.sp_MSscript_trigger_update_checks @objid, null, null, 'pk', 0 end -- 2nd preamble common to all synctran procs exec dbo.sp_MSscript_begintrig2 @objid, 'upd' -- script single row handling exec @rc = dbo.sp_MSscript_singlerow_trigger @objid,@publisher, @publisher_db, @procname, @proc_owner, @identity_col, @ts_col, 'upd', @primary_key_bitmap -- script multi-row handling exec @rc = dbo.sp_MSscript_multirow_trigger @objid,@publisher, @publisher_db, @procname, @proc_owner, @identity_col, @ts_col, 'upd', @primary_key_bitmap -- script end of trigger exec dbo.sp_MSscript_endtrig -- send fragments to client select procedure_text from #proctext order by c1 asc end go raiserror('Creating procedure sp_MSscript_sync_del_trig', 0,1) go create procedure sp_MSscript_sync_del_trig @objid int, @publisher sysname, @publisher_db sysname, @trigname sysname, @procname sysname, @proc_owner sysname, @identity_col sysname = NULL, @ts_col sysname = NULL, @filter_clause nvarchar(4000), @primary_key_bitmap varbinary(4000) as 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 declare @qualname nvarchar(512) set nocount on exec sp_MSget_qualified_name @objid, @qualname OUTPUT if @ts_col in ('null','NULL') select @ts_col = null if @identity_col in ('null','NULL') select @identity_col = null if @ts_col is null begin -- row compare method only supports updates select N'create trigger ' + QUOTENAME(@trigname) + N' on ' + @qualname + N' for delete not for replication ' + N'as ' + N' exec sp_MSreplraiserror 20518 ' + N' rollback transaction ' end else begin exec @indid = dbo.sp_MStable_has_unique_index @objid -- Create temp table create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL) -- 1st preamble common to all synctran procs exec dbo.sp_MSscript_begintrig1 @trigname, @objid, @procname, @filter_clause, 'del' -- 2nd preamble common to all synctran procs exec dbo.sp_MSscript_begintrig2 @objid, 'del' -- script single row handling exec @rc = dbo.sp_MSscript_singlerow_trigger @objid,@publisher, @publisher_db, @procname, @proc_owner, @identity_col, @ts_col, 'del', @primary_key_bitmap -- script multi-row handling exec @rc = dbo.sp_MSscript_multirow_trigger @objid,@publisher, @publisher_db, @procname, @proc_owner, @identity_col, @ts_col, 'del', @primary_key_bitmap -- script end of trigger exec dbo.sp_MSscript_endtrig -- send fragments to client select procedure_text from #proctext order by c1 asc end 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, @column nvarchar(4000) output, @from_proc bit = 0, @coltype sysname = NULL, @type varchar(10) = NULL 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 + (@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 [' + @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 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 -- 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 /* ** 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' END -- 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 raiserror('Creating procedure sp_helpreplicationdboption', 0,1) go CREATE PROCEDURE sp_helpreplicationdboption @dbname sysname = '%', @type sysname = 'replication allowed' AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @retcode int, @typebit int /* bit to distinguish distribution databases */ DECLARE @distbit int SELECT @distbit = 16 DECLARE @dbowner bit SELECT @dbowner = 0 DECLARE @replication_db sysname -- bug 24437 don't do security check. if (lower(@type) like 'publish%') select @typebit = 1 else if (lower(@type) like 'subscribe%') select @typebit = 2 else if (lower(@type) like 'merge publish%') select @typebit = 4 else if (lower(@type) like 'merge subscribe%') select @typebit = 8 else if (lower(@type) like 'replication allowed%') select @typebit = 0 else begin raiserror(14091,-1,-1) return 1 end /* ** Parameter Check: @dbname. ** Check to make sure that the database name conforms to the rules ** for identifiers. */ IF @dbname <> '%' BEGIN EXECUTE @retcode = dbo.sp_validname @dbname IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) END /* ** Show databases with this option enabled. */ CREATE TABLE #replicationdbs (name sysname NOT NULL, id int identity NOT NULL, transpublish bit not null, mergepublish bit not null, dbowner bit not null) if @typebit <> 0 begin INSERT INTO #replicationdbs (name, transpublish, mergepublish, dbowner) SELECT name, case when (category & 1) <> 0 then 1 else 0 end, case when (category & 4) <> 0 then 1 else 0 end, @dbowner FROM master..sysdatabases WHERE name LIKE @dbname AND (category & @typebit) <> 0 and (isnull(databaseproperty(name, N'issuspect'), 0) = 0 and isnull(databaseproperty(name, N'isshutdown'), 0) = 0) DECLARE hCdboinfo CURSOR LOCAL FAST_FORWARD FOR SELECT name FROM #replicationdbs FOR READ ONLY OPEN hCdboinfo FETCH hCdboinfo INTO @replication_db WHILE (@@fetch_status <> -1) BEGIN EXEC @retcode = sp_MSrepl_isdbowner @replication_db IF (@retcode IS NOT NULL) AND (@retcode <> 0) BEGIN UPDATE #replicationdbs set dbowner = 1 where name = @replication_db END FETCH hCdboinfo INTO @replication_db END CLOSE hCdboinfo DEALLOCATE hCdboinfo SELECT * FROM #replicationdbs end else begin DECLARE @db_category int /* Filter out distribution databases */ DECLARE hC CURSOR LOCAL FAST_FORWARD FOR SELECT name, category FROM master..sysdatabases WHERE name LIKE @dbname AND (category & @distbit) = 0 and (isnull(databaseproperty(name, N'issuspect'), 0) = 0 and isnull(databaseproperty(name, N'isshutdown'), 0) = 0) FOR READ ONLY OPEN hC FETCH hC INTO @replication_db, @db_category WHILE (@@fetch_status <> -1) BEGIN if @replication_db <> 'master' AND @replication_db <> 'model' AND @replication_db <> 'tempdb' AND @replication_db <> 'msdb' AND @replication_db <> 'MSSQLWeb' BEGIN EXEC @retcode = sp_MSrepl_isdbowner @replication_db IF (@retcode IS NOT NULL) AND (@retcode <> 0) BEGIN SELECT @dbowner = 1 END ELSE BEGIN SELECT @dbowner = 0 END INSERT INTO #replicationdbs (name, transpublish, mergepublish, dbowner) VALUES (@replication_db, case when (@db_category & 1) <> 0 then 1 else 0 end, case when (@db_category & 4) <> 0 then 1 else 0 end, @dbowner) END FETCH hC INTO @replication_db, @db_category END CLOSE hC DEALLOCATE hC SELECT * FROM #replicationdbs end DROP TABLE #replicationdbs 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 > 1 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 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 sysmergesubscriptions where pubid = @pubid and status <> 2 delete from sysmergepublications where pubid = @pubid delete from sysmergeschemachange where pubid = @pubid GO exec dbo.sp_MS_marksystemobject sp_MSpublicationcleanup go grant execute on dbo.sp_MSpublicationcleanup to public 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) -- 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, @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) /* 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 exec dbo.sp_MS_marksystemobject sp_MSarticlecleanup go grant execute on dbo.sp_MSarticlecleanup to public go raiserror('Creating procedure sp_MSdroparticleprocs', 0,1) GO create procedure sp_MSdroparticleprocs (@pubid uniqueidentifier, @artid uniqueidentifier) as set nocount on declare @ins_procname sysname declare @upd_procname sysname declare @conf_procname sysname declare @sel_procname sysname declare @tmp_procname nvarchar(260) declare @view_sel_proc sysname declare @owner sysname declare @objid int -- get the insert, update and conflict proc names from sysmergearticles select @ins_procname = insert_proc, @upd_procname = update_proc, @sel_procname = select_proc, @conf_procname = ins_conflict_proc, @view_sel_proc = view_sel_proc, @objid = objid from sysmergearticles where pubid = @pubid and artid = @artid if (@ins_procname IS NOT NULL) and exists (select * from sysobjects where name = @ins_procname and type = 'P') begin select @owner = user_name(uid) from sysobjects where name=@ins_procname select @tmp_procname = QUOTENAME(@owner) + '.' + QUOTENAME(@ins_procname) exec ('drop proc ' + @tmp_procname) if @@ERROR<>0 return (1) update sysmergearticles set insert_proc = NULL where pubid=@pubid and artid=@artid end if (@upd_procname IS NOT NULL) and exists (select * from sysobjects where name = @upd_procname and type = 'P') begin select @owner = user_name(uid) from sysobjects where name=@upd_procname select @tmp_procname = QUOTENAME(@owner) + '.' + QUOTENAME(@upd_procname) exec ('drop proc ' + @tmp_procname) if @@ERROR<>0 return (1) update sysmergearticles set update_proc = NULL where pubid=@pubid and artid=@artid end if (@sel_procname IS NOT NULL) and exists (select * from sysobjects where name = @sel_procname and type = 'P') begin select @owner = user_name(uid) from sysobjects where name=@sel_procname select @tmp_procname = QUOTENAME(@owner) + '.' + QUOTENAME(@sel_procname) exec ('drop proc ' + @tmp_procname) if @@ERROR<>0 return (1) update sysmergearticles set select_proc = NULL where pubid=@pubid and artid=@artid end if (@view_sel_proc IS NOT NULL) and exists (select * from sysobjects where name = @view_sel_proc and type = 'P') begin select @owner = user_name(uid) from sysobjects where name=@view_sel_proc select @tmp_procname = QUOTENAME(@owner) + '.' + QUOTENAME(@view_sel_proc) exec ('drop proc ' + @tmp_procname) if @@ERROR<>0 return (1) update sysmergearticles set view_sel_proc = NULL where pubid=@pubid and artid=@artid end if (@conf_procname IS NOT NULL) and not exists (select * from sysmergearticles where artid=@artid and pubid<>@pubid) and exists (select * from sysobjects where name = @conf_procname and type = 'P') begin select @owner = user_name(uid) from sysobjects where name=@conf_procname select @tmp_procname = QUOTENAME(@owner) + '.' + QUOTENAME(@conf_procname) exec ('drop proc ' + @tmp_procname) if @@ERROR<>0 return (1) update sysmergearticles set ins_conflict_proc = NULL where pubid=@pubid and artid=@artid end return 0 GO exec dbo.sp_MS_marksystemobject sp_MSdroparticleprocs go raiserror('Creating procedure sp_MSdroparticletriggers', 0,1) GO create procedure sp_MSdroparticletriggers (@source_table nvarchar(258)) as set nocount on declare @instrigger sysname declare @updtrigger sysname declare @deltrigger sysname declare @retcode int declare @owner sysname declare @artid uniqueidentifier declare @guidstr nvarchar(32) -- PARSENAME VARS declare @UnqualName sysname --rightmost name node declare @QualName1 sysname -- END PARSENAME VARS select @UnqualName = PARSENAME(@source_table, 1) select @QualName1 = PARSENAME(@source_table, 2) if @UnqualName IS NULL return 1 if @QualName1 is not NULL select @owner = @QualName1 else select @owner = 'dbo' select @artid = artid from sysmergearticles where objid = object_id(@source_table) exec @retcode=sp_MSguidtostr @artid, @guidstr out if @retcode<>0 or @@ERROR<>0 return (1) set @instrigger = @owner + '.ins_' + @guidstr set @updtrigger = @owner + '.upd_' + @guidstr set @deltrigger = @owner + '.del_' + @guidstr /* select @instrigger = sysobjects.name from sysobjects where ObjectProperty (sysobjects.id, 'ExecIsInsertTrigger') = 1 and ObjectProperty (sysobjects.id, 'IsMSShipped') = 1 and parent_obj = OBJECT_ID(@source_table) select @updtrigger = sysobjects.name from sysobjects where ObjectProperty (sysobjects.id, 'ExecIsUpdateTrigger') = 1 and ObjectProperty (sysobjects.id, 'IsMSShipped') = 1 and parent_obj = OBJECT_ID(@source_table) select @deltrigger = sysobjects.name from sysobjects where ObjectProperty (sysobjects.id, 'ExecIsDeleteTrigger') = 1 and ObjectProperty (sysobjects.id, 'IsMSShipped') = 1 and parent_obj = OBJECT_ID(@source_table) */ if object_id(@instrigger) is not NULL begin exec ('drop trigger ' + @instrigger) if @@ERROR<>0 return (1) end if object_id(@updtrigger) is not NULL begin exec ('drop trigger ' + @updtrigger) if @@ERROR<>0 return (1) end if object_id(@deltrigger) IS NOT NULL begin exec ('drop trigger ' + @deltrigger) if @@ERROR<>0 return (1) end return 0 GO exec dbo.sp_MS_marksystemobject sp_MSdroparticletriggers go grant execute on dbo.sp_MSdroparticletriggers to public raiserror('Creating procedure sp_mergesubscription_cleanup', 0,1) GO CREATE PROCEDURE sp_mergesubscription_cleanup ( @publisher sysname, @publisher_db sysname, @publication sysname ) AS declare @pubid uniqueidentifier declare @parentid uniqueidentifier declare @artid uniqueidentifier declare @retcode smallint declare @subscription_type int /* ** if there is nothing to cleanup, then just return. */ if not exists (select * from sysobjects where name='sysmergesubscriptions') return (0) /* 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) select @subscription_type = subscription_type from sysmergesubscriptions where pubid=@pubid and subid<>pubid /* This procedure is not intended to be used for cleanning-up pull/anonymous subscriptions */ if @subscription_type > 0 begin raiserror(20091, 16, -1) return (1) end /* 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) delete from sysmergesubscriptions where pubid = @pubid delete from sysmergepublications where pubid = @pubid delete from sysmergeschemachange where pubid = @pubid GO exec dbo.sp_MS_marksystemobject sp_mergesubscription_cleanup go grant execute on dbo.sp_mergesubscription_cleanup to public 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, MSreplication_subscriptions s where (UPPER(s.publisher) = UPPER(@publisher) AND s.publisher_db = @publisher_db AND (s.publication = @publication or s.independent_agent = @independent_agent) and o.publisher = @publisher and o.publisher_db = @publisher_db and (o.publication = s.publication or @independent_agent = 0)) 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 exec dbo.sp_MS_marksystemobject sp_subscription_cleanup go raiserror('Creating procedure sp_get_distributor', 0,1) go -- Called by the UI to find out if the distributor is installed without doing RPC. CREATE PROCEDURE sp_get_distributor AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @distributor sysname DECLARE @installed bit declare @distdb_installed bit declare @is_distpublisher bit declare @has_remote_distpublisher bit declare @distbit int SELECT @distbit = 16 SELECT @distributor = datasource FROM master..sysservers WHERE srvstatus & 8 <> 0 if @distributor is not null select @installed = 1 else select @installed = 0 if UPPER(@distributor) = UPPER(@@servername) begin if exists (select * from msdb.dbo.MSdistributiondbs) select @distdb_installed = 1 else select @distdb_installed = 0 if exists (select * from msdb..MSdistpublishers where UPPER(name) = UPPER(@@servername)) select @is_distpublisher = 1 else select @is_distpublisher = 0 if exists (select * from msdb..MSdistpublishers where UPPER(name) <> UPPER(@@servername)) select @has_remote_distpublisher = 1 else select @has_remote_distpublisher = 0 end else begin select @distdb_installed = 0 select @has_remote_distpublisher = 0 select @is_distpublisher = 0 end select 'installed' = @installed, 'distribution server' = @distributor, 'distribution db installed' = @distdb_installed, 'is distribution publisher' = @is_distpublisher, 'has remote distribution publisher' = @has_remote_distpublisher GO exec dbo.sp_MS_marksystemobject sp_get_distributor go -- Called by sp_addrolemember raiserror('Creating procedure sp_MSrepl_addrolemember', 0,1) go CREATE PROCEDURE sp_MSrepl_addrolemember @rolename sysname, @membername sysname AS -- SETUP RUNTIME OPTIONS / DECLARE VARIABLES -- set nocount on return(0) go exec dbo.sp_MS_marksystemobject sp_MSrepl_addrolemember go -- Called by sp_droprolemember raiserror('Creating procedure sp_MSrepl_droprolemember', 0,1) go CREATE PROCEDURE sp_MSrepl_droprolemember @rolename sysname, @membername sysname AS set nocount on return(0) go exec dbo.sp_MS_marksystemobject sp_MSrepl_droprolemember go raiserror('Creating procedure sp_table_validation', 0,1) go create procedure sp_table_validation @table sysname, -- table name or sync object name @expected_rowcount int = NULL OUTPUT, @expected_checksum numeric = NULL OUTPUT, @rowcount_only bit = 1, @owner sysname = NULL, @full_or_fast tinyint = 2, -- full (value 0) does COUNT(*) -- fast (value 1) uses sysindexes.rows if table (not view); -- conditional fast (VALUE 2) , first tries fast method, but -- reverts to full if fast method shows differences. @shutdown_agent bit = 0, -- If 1 will raise error 20578, which will signal replication agent to shutdown @table_name sysname = NULL -- table name of sync object or the table name for output message as set nocount on declare @num_rows int -- RHS: original proc by CC used INT. -- But INT will not be acceptable longer term - table may have more than 2bil rows -- For now, leave it at INT and come back and improve this later. declare @checksum numeric declare @checksum_string varchar(100) declare @expected_checksum_string varchar(100) declare @width int declare @qualified_table_name nvarchar(262) -- two names plus []'s and a . declare @temp_table_used bit declare @retstatus int declare @failed_fast tinyint declare @min_indid int declare @asked_for_exp_checksum tinyint declare @asked_for_exp_rows tinyint -- declare @debug tinyint -- Temporary. Take this out before beta 3 (or when TSQL debugger comes online) SET @retstatus=0 -- initialize to SUCCESS SET @failed_fast=0 -- SET @debug=0 if (@expected_checksum IS NULL AND @rowcount_only = 0 ) -- Wants an expected checksum value SET @asked_for_exp_checksum=1 ELSE SET @asked_for_exp_checksum=0 if (@expected_rowcount IS NULL) -- Wants an expected checksum value SET @asked_for_exp_rows=1 ELSE SET @asked_for_exp_rows=0 -- RHS: Should go back and do better parameter checking here -- Some states do not make sense. For example, it does not make sense to ask for conditional -- fast row count checking, yet not provide an expected value. If this is done, provide a warning -- message and use fast checking method. if (@full_or_fast = 2 AND @expected_rowcount IS NULL) BEGIN -- Msg 20559,'Conditional Fast Rowcount method requested without specifying an expected count. Fast method will be used.' raiserror (20559, 10, -1) SET @full_or_fast = 1 END -- Another state that doesn't make sense is to pass an expected checksum value, yet -- ask for rowcount only validation if (@expected_checksum IS NOT NULL AND @rowcount_only > 0) BEGIN -- Msg 20560,'An expected checksum value was passed, but checksums will not be compared because Rowcount only checking was requested.' raiserror (20560, 10, -1) SET @expected_checksum = NULL END if @owner is null begin if left(ltrim(rtrim(@table)), 1) <> '[' or right(ltrim(rtrim(@table)), 1) <> ']' set @qualified_table_name = '[' + @table + ']' else set @qualified_table_name = @table end else begin if left(ltrim(rtrim(@table)), 1) <> '[' or right(ltrim(rtrim(@table)), 1) <> ']' set @qualified_table_name = '[' + @owner + '].[' + @table + ']' else set @qualified_table_name = '[' + @owner + '].' + @table end -- If the object is a table (not view) and fast checking (1) requested, -- then get rowcount from sysindexes, rather than scanning IF (SELECT @full_or_fast) > 0 -- IF Fast row checking asked for AND (SELECT OBJECTPROPERTY(OBJECT_ID(@qualified_table_name),'IsTable')) > 0 -- Must be a table, not a view BEGIN -- Do the fast rowcount method -- Temporarily put a SHARE lock on table to ensure no simultaneous updates going on -- Minimizes chances of getting an out of date value from sysindexes. True that -- it reduces concurrency, but if the fast method doesnt work the user will very likely -- go do the full method, which will be much more costly. Better I think to take a little more cost here -- and hopefully get a good number. The @foo variable is used so that its an -- assignment and doesn't make another result set get returned. -- DEBUG -- if @debug=1 PRINT "Querying for fast rowcount" BEGIN TRAN EXEC ('DECLARE @foo int SELECT @foo=1 FROM ' + @qualified_table_name + ' (TABLOCK HOLDLOCK) WHERE 1=2') SELECT @num_rows=rows,@min_indid=indid FROM sysindexes WHERE id=OBJECT_ID(@qualified_table_name)and indid < 2 COMMIT TRAN END ELSE BEGIN -- if @debug=1 PRINT "setting variable to use full row count" SET @full_or_fast = 0 -- Full checking will be used, regardless of whether it was requested END -- set the output name if not set if (@table_name IS NULL) SELECT @table_name = @table -- If fast row checking was used, and request for rowcount check only, we're done. if (@full_or_fast = 1 AND @rowcount_only > 0) BEGIN -- if @debug=1 PRINT "fast rowcount only requested & done - going to rowcount msg" GOTO ROWCOUNT_MSG END -- If conditional fast row checking was used, and request for rowcount check only, -- we're also done IFF rows and expected rows match. if (@full_or_fast = 2 AND @rowcount_only > 0 AND @expected_rowcount IS NOT NULL AND @expected_rowcount=@num_rows) BEGIN -- Fast checking was actually used. -- if @debug=1 PRINT "conditional fast rowcount requested & passed - going to rowcount msg" SET @full_or_fast = 1 GOTO ROWCOUNT_MSG END -- If we're still here we are doing full row checking at a minimum, and will need the temp table IF (SELECT ISNULL(OBJECT_ID('tempdb..#tab_validt1'),0)) = 0 -- Table Does Not exist CREATE TABLE #tab_validt1 (tmp_rows int NULL, tmp_checksum numeric NULL) ELSE -- table already exists TRUNCATE TABLE #tab_validt1 -- If we are only doing row checking, we'll do it here. If we will do both row checking -- and checksum, then do them together so as to not scan table twice. if @rowcount_only = 1 BEGIN -- Must do full count(*) checking but not checksums if @full_or_fast=2 -- if we are here with conditional check (2) requested, it is because -- a conditional was possible, but it failed. We wiil later alert user of this. BEGIN SET @full_or_fast=0 SET @failed_fast=1 END insert into #tab_validt1 (tmp_rows,tmp_checksum) exec ('select count(*), NULL from ' + @qualified_table_name + ' (TABLOCK HOLDLOCK)') -- Get row count value select TOP 1 @num_rows = tmp_rows from #tab_validt1 -- Should only be one row -- if @debug=1 SELECT 'The TEMP TABLE HAS THIS MANY ROWS',count(*) from #tab_validt1 -- IF there were no rows from above, the table was empty so use ZERO. IF @num_rows IS NULL SELECT @num_rows=0 -- Done with the temp table DROP TABLE #tab_validt1 IF @expected_rowcount IS NULL BEGIN SET @expected_rowcount = @num_rows END GOTO ROWCOUNT_MSG END -- Done with full row count only ELSE -- Doing checksums in addition to ROWCOUNT BEGIN -- DO checksum and rowcount in same pass thru the table insert into #tab_validt1 (tmp_rows,tmp_checksum) exec ('select count(*), sum (convert(numeric, getchecksum(NULL,1))) from ' + @qualified_table_name + ' (TABLOCK HOLDLOCK)') -- Get the checksum & rowcount values select TOP 1 @checksum = tmp_checksum, @num_rows= tmp_rows from #tab_validt1 -- IF there were no rows from above, the table was empty so use ZERO. IF @checksum IS NULL or @num_rows IS NULL SELECT @checksum=isnull(@checksum,0),@num_rows=isnull(@checksum,0) -- Done with the temp table DROP TABLE #tab_validt1 IF @expected_rowcount IS NULL -- Just getting value - no expected value yet. SET @expected_rowcount = @num_rows -- Validate checksum IF @expected_checksum is null -- Just getting value - no expected value yet. set @expected_checksum = @checksum else -- Raise error if checksums OR rowcounts do not match if @checksum <> @expected_checksum OR @num_rows <> @expected_rowcount begin -- Checksum failed. set @checksum_string = convert(varchar(21), @checksum) set @expected_checksum_string = convert(varchar(21), @expected_checksum) -- Msg 20525: Table ''%s'' is out of synchronization. Rowcounts (actual: %d, expected %d). Checksum difference (actual: %s, expected: %s).' raiserror (20525, 10, -1, @table, @num_rows, @expected_rowcount, @checksum_string, @expected_checksum_string) SET @retstatus=1 END else BEGIN -- Row count and checksum validation passed. -- if @asked_for_exp_checksum=0 -- Only give message if not generating the expected value raiserror (20527, 10, -1, @table,@num_rows) END -- Done with checksum and rowcount scan. END -- We did checksum method, and so are done and skip over the rowcount only messages. GOTO ALL_DONE ROWCOUNT_MSG: -- Raise error if rows counts do not match IF @expected_rowcount IS NULL -- just return the found value SET @expected_rowcount=@num_rows ELSE IF @num_rows <> @expected_rowcount begin -- Msg 20524: 'Table ''%s'' may be out of synchronization. Row count difference encountered (actual: %d, expected: %d). Row count method %d used. (0=Full 1=Fast)', NULL) raiserror (20524, 10, -1, @table_name, @num_rows, @expected_rowcount, @full_or_fast ) SET @retstatus=1 end ELSE -- Row count validation passed. begin if @asked_for_exp_rows=0 -- Only give message if not generating the expected value -- Msg 20526: 'Table ''%s'' passed row count (%d) validation. Row count method %d used. (0=Full 1=Fast)'' raiserror (20526, 10, -1, @table_name, @num_rows, @full_or_fast) if @failed_fast=1 BEGIN -- if we had to revert to FULL on a CONDITIONAL FAST, Make that known too. -- And Update usage to fix the problem -- Msg 20558: 'Table ''%s'' passed full row count validation after failing the fast check. DBCC UPDATEUSAGE will be automatically initiated.' raiserror (20558, 10, -1, @table_name) DBCC UPDATEUSAGE (0,@qualified_table_name,@min_indid) WITH COUNT_ROWS, NO_INFOMSGS END end ALL_DONE: -- Give nice message if only generating the expected value: -- Msg for rows and checksum: if @asked_for_exp_checksum=1 and @asked_for_exp_rows=1 -- Only give message if generating the expected value BEGIN set @expected_checksum_string = convert(varchar(21), @expected_checksum) -- Msg 20579:'Generated expected rowcount value of %d and expected checksum value of %s for %s .' raiserror (20579, 10, -1, @expected_rowcount,@expected_checksum_string,@table_name) END ELSE BEGIN if @asked_for_exp_checksum=0 and @asked_for_exp_rows=1 -- Msg 20561:'Generated expected rowcount value of %d for %s .', 1033) raiserror (20561, 10, -1, @expected_rowcount, @table_name) END -- Raise error that will shutdown replication agents if @shutdown_agent = 1 --Msg 20578: 'Shutdown replication agent request.' raiserror (20578, 10, -1) return @retstatus go exec dbo.sp_MS_marksystemobject sp_table_validation go /* Create sp_removedbreplication */ raiserror('Creating procedure sp_removedbreplication', 0,1) GO /* Permission to sysadmin */ CREATE PROCEDURE sp_removedbreplication ( @dbname sysname ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @retcode int DECLARE @proc nvarchar(255) DECLARE @optbit int DECLARE @restoreoverride int /* ** Initialization */ /* ** Support override of replication remove on attach and restore */ SELECT @restoreoverride = 0 -- assume normal remove behavior 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 /* ** Parameter check ** @dbname */ IF NOT EXISTS (SELECT * FROM master.dbo.sysdatabases WHERE name = @dbname) BEGIN RAISERROR(15010, 16, -1, @dbname) RETURN(1) END SELECT @proc = quotename(@dbname) + '.dbo.sp_MSremovedbreplication' EXEC @retcode = @proc IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END -- Clear tran bit SELECT @optbit = 1 IF EXISTS (SELECT * FROM master..sysdatabases WHERE name = @dbname AND (category & @optbit) <> 0) begin /* ** Toggle the category bit in master..sysdatabases */ UPDATE master..sysdatabases SET category = category & ~@optbit WHERE name = @dbname IF @@ERROR <> 0 BEGIN return (1) END end -- Clear merge bit SELECT @optbit = 4 IF EXISTS (SELECT * FROM master..sysdatabases WHERE name = @dbname AND (category & @optbit) <> 0) begin /* ** Toggle the category bit in master..sysdatabases */ UPDATE master..sysdatabases SET category = category & ~@optbit WHERE name = @dbname IF @@ERROR <> 0 BEGIN return (1) END end /* * Bug 47732 - cannot checkpoint in attach or restore * CHECKPOINT * IF @@ERROR <> 0 * BEGIN * return (1) * END */ GO exec dbo.sp_MS_marksystemobject sp_removedbreplication go raiserror('Creating procedure sp_removesrvreplication', 0,1) GO create procedure sp_removesrvreplication as begin /* * unmark replication bits for all servers, databases; used by setup in vupgrade * assumes override is on; db in single user mode * no need to check rowcounts affected by updates, may not be any repl dbs * failure label avoids repetition of errs if not in single user mode */ set nocount on -- server bits declare @srv_distbit int declare @srv_pubbit int declare @srv_subbit int declare @srv_dsnbit int select @srv_distbit = 8, @srv_pubbit = 16, @srv_subbit = 4, @srv_dsnbit = 32 -- dsn subscriber -- db bits declare @db_tranbit int declare @db_mergbit int declare @db_distbit int select @db_tranbit = 1, @db_mergbit = 4, @db_distbit = 16 -- setup attach overrides removedb option declare @dbname sysname declare cur_db CURSOR LOCAL FAST_FORWARD for select name from master..sysdatabases where name <> N'master' for read only open cur_db fetch cur_db into @dbname while ( @@fetch_status <> -1 ) begin exec dbo.sp_removedbreplication @dbname -- clean up system tables exec ( @dbname + '.dbo.sp_MSdrop_pub_tables' ) exec ( @dbname + '.dbo.sp_MSdrop_mergesystables' ) fetch next from cur_db into @dbname end close cur_db deallocate cur_db -- unmark db bits -- select name, category from sysdatabases where category & @tranbit = @tranbit update master..sysdatabases set category = category & ~@db_tranbit where category & @db_tranbit = @db_tranbit if @@ERROR <> 0 goto fail update master..sysdatabases set category = category & ~@db_mergbit where category & @db_mergbit = @db_mergbit if @@ERROR <> 0 goto fail -- clean up old dist db bit update master..sysdatabases set category = category & ~@db_distbit where category & @db_distbit = @db_distbit if @@ERROR <> 0 goto fail -- unmark srv bits (srvstatus = @dsnbit no longer used by replication subscribers but by server ) -- select name, srvstatus from sysservers where srvstatus & @srv_distbit = @srv_distbit update master..sysservers set srvstatus = srvstatus & ~@srv_subbit where srvstatus & @srv_subbit = @srv_subbit if @@ERROR <> 0 goto fail update master..sysservers set srvstatus = srvstatus & ~@srv_pubbit where srvstatus & @srv_pubbit = @srv_pubbit if @@ERROR <> 0 goto fail update master..sysservers set srvstatus = srvstatus & ~@srv_distbit where srvstatus & @srv_distbit = @srv_distbit if @@ERROR <> 0 goto fail return (0) fail: -- ad hoc updates not allowed and not single user return (1) end go exec dbo.sp_MS_marksystemobject sp_removesrvreplication go raiserror('Creating procedure sp_MSremovedbreplication', 0,1) GO CREATE PROCEDURE sp_MSremovedbreplication AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @retcode int if exists (select * from sysobjects where name = 'sysarticles') -- clean up transactional begin if not exists (select * from master..MSreplication_options where optname = 'transactional') begin RAISERROR(21027, 16, -1, 'transactional') return(1) end EXEC @retcode = dbo.sp_MSpublishdb @value = 'false', @ignore_distributor = 1 IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END end if exists (select * from sysobjects where name = 'sysmergearticles') -- clean up merge -- can not use sp_MSmergepublishdb or sp_dropmergepullsubscriptions -- since they depend on serverid and dbname begin declare @pubid uniqueidentifier declare @artid uniqueidentifier declare hC CURSOR LOCAL FAST_FORWARD FOR select DISTINCT pubid, artid FROM sysmergearticles FOR READ ONLY OPEN hC FETCH hC INTO @pubid, @artid WHILE (@@fetch_status <> -1) begin EXEC @retcode = dbo.sp_MSarticlecleanup @pubid, @artid IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) end FETCH hC INTO @pubid, @artid end execute @retcode = dbo.sp_MSdrop_mergesystables if @@ERROR <> 0 or @retcode <> 0 begin return (1) end end if exists (select * from sysobjects where name = 'MSreplication_subscriptions') -- clean up tran sub begin -- drop pull subscription EXEC @retcode = dbo.sp_droppullsubscription @publisher = N'all', @publisher_db = N'all', @publication = N'all' IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END -- drop push subscription EXEC @retcode = dbo.sp_subscription_cleanup @publisher = N'all', @publisher_db = N'all', @publication = N'all', @reserved = 'drop_all' IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END end GO exec dbo.sp_MS_marksystemobject sp_MSremovedbreplication 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_MSsubscription_properties') exec ('use '+ @dbname + ' exec dbo.sp_vupgrade_mergetables') fetch next from current_db into @dbname end close current_db deallocate current_db go raiserror('Creating procedure sp_vupgrade_mergetables', 0,1) GO create procedure sp_vupgrade_mergetables as declare @artnick int declare @objid int declare @ccols int declare @goodlen int declare @col_track int declare @article sysname declare @pubid uniqueidentifier declare @pubname sysname declare @qualified_name nvarchar(257) declare @source_owner sysname declare @source_object sysname if (exists (select * from sysobjects where name = 'sysmergearticles')) begin -- A column has 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 -- an index has been added on genhistory(guidlocal) if not exists (select * from sysindexes where name = 'nc2MSmerge_genhistory') begin create index nc2MSmerge_genhistory on MSmerge_genhistory(guidlocal) if @@ERROR <> 0 return 1 end -- previous builds had a bug that caused truncated colv metadata select @artnick = min(nickname) from sysmergearticles while @artnick is not null begin -- find base table to compute number of columns select @objid = objid, @col_track = column_tracking, @article = name from sysmergearticles where nickname = @artnick select @pubname = min(name) from sysmergepublications where pubid in (select pubid from sysmergearticles where nickname = @artnick) while @pubname is not null begin -- remake the articles procs exec sp_MSsetartprocs @pubname, @article, 1 select @pubname = min(name) from sysmergepublications where name > @pubname and pubid in (select pubid from sysmergearticles where nickname = @artnick) end -- regenerate the triggers select @source_owner = user_name(uid), @source_object = name from sysobjects where id = @objid select @qualified_name = QUOTENAME(@source_owner) + '.' + QUOTENAME(@source_object) exec sp_MSaddmergetriggers @qualified_name, @col_track if @col_track = 1 begin select @ccols = count(*) from syscolumns where id = @objid -- compute expected length of colv1 set @goodlen = 8 * @ccols if @goodlen > 2040 set @goodlen = 2040 -- delete metadata that has truncated colv delete from MSmerge_contents where tablenick = @artnick and datalength(colv1) < @goodlen end -- find next article select @artnick = min(nickname) from sysmergearticles where nickname > @artnick end -- Loop over publications and recreate the views select @pubname = min(name) from sysmergepublications where UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name() while @pubname is not null begin -- remake the publication views exec sp_MSpublicationview @pubname, 1 select @pubname = min(name) from sysmergepublications where name > @pubname and UPPER(publisher)=UPPER(@@SERVERNAME) and publisher_db=db_name() end end GO raiserror('Creating procedure sp_vupgrade_MSsubscription_properties', 0,1) GO create procedure sp_vupgrade_MSsubscription_properties as -- Add FTP properties to MSsubscription_properties. These where added after B3 of 7.0 -- and before RTM. IF EXISTS (SELECT * FROM sysobjects WHERE name = 'MSsubscription_properties' and type = 'U') begin if not exists (select * from syscolumns where name = 'ftp_address' and id = OBJECT_ID('MSsubscription_properties')) begin alter table MSsubscription_properties ADD ftp_address sysname NULL if @@ERROR <> 0 return 1 end if not exists (select * from syscolumns where name = 'ftp_port' and id = OBJECT_ID('MSsubscription_properties')) begin alter table MSsubscription_properties ADD ftp_port int NULL if @@ERROR <> 0 return 1 end if not exists (select * from syscolumns where name = 'ftp_login' and id = OBJECT_ID('MSsubscription_properties')) begin alter table MSsubscription_properties ADD ftp_login sysname NULL if @@ERROR <> 0 return 1 end if not exists (select * from syscolumns where name = 'ftp_password' and id = OBJECT_ID('MSsubscription_properties')) begin alter table MSsubscription_properties ADD ftp_password sysname NULL if @@ERROR <> 0 return 1 end end 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 = 517, @force_remove tinyint = 0 ) as begin /* * Stub to handle possible need to modify or supplement replication metadata during setup * initiated version upgrade from Beta 3 (and subsequent builds) to RTM. 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 declare @ver_retention int select @platform_nt = 0x1 select @ver_min= 517 select @ver_retention = 576 --build # on 9/17 if ( @ver_old < @ver_min ) or ( @force_remove = 1 ) exec dbo.sp_removesrvreplication 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 if (@osql_for_nt = 1) select @osql_cmd = '" ' else select @osql_cmd = ' ' 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 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 = 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 exec @retcode = dbo.sp_vupgrade_publisher @ver_old = @ver_old, @ver_retention = @ver_retention if @retcode<>0 or @@error<>0 return (1) -- Update subscription database schema exec @retcode = dbo.sp_vupgrade_subscription_databases if @retcode <> 0 or @@error <> 0 return (1) end return (0) end go exec dbo.sp_MS_marksystemobject sp_vupgrade_replication go raiserror('Creating procedure sp_vupgrade_publisher', 0,1) go create procedure sp_vupgrade_publisher @ver_old int, @ver_retention int as SET NOCOUNT ON declare @proc_name nvarchar(200) declare @publication sysname declare @upgraded bit declare @retcode int declare @publisher_db sysname declare @agentname sysname /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) /* ** Get distribution server information for remote RPC call. */ -- Get expired subscription cleanup agent name set @agentname = formatmessage(20569) UPDATE msdb.dbo.sysjobs SET name = @agentname FROM msdb.dbo.sysjobs, msdb.dbo.sysjobsteps as s WHERE msdb.dbo.sysjobs.job_id = s.job_id AND ( UPPER(s.command) = UPPER(N'EXEC sp_MScleanup_subscription') OR UPPER(s.command) = UPPER(N'EXEC dbo.sp_MScleanup_subscription') ) UPDATE msdb.dbo.sysjobsteps SET command = N'EXEC dbo.sp_expired_subscription_cleanup' WHERE UPPER(command) = UPPER(N'EXEC sp_MScleanup_subscription') OR UPPER(command) = UPPER(N'EXEC dbo.sp_MScleanup_subscription') DECLARE DC CURSOR LOCAL FAST_FORWARD for select DISTINCT name from master..sysdatabases -- Merge schema change should happen on all dbs since the sub db is not marked for publish. -- where ((category & 4) = 4) or ((category & 1) = 1) for read only open DC fetch DC into @publisher_db WHILE (@@fetch_status <> -1) BEGIN select @proc_name = @publisher_db + '.dbo.sp_vupgrade_publisherdb' exec @retcode = @proc_name @ver_old = @ver_old, @ver_retention = @ver_retention if @retcode<>0 or @@ERROR<>0 begin close DC deallocate DC return (1) end fetch DC into @publisher_db END close DC deallocate DC GO exec dbo.sp_MS_marksystemobject sp_vupgrade_publisher go grant execute on dbo.sp_vupgrade_publisher to public go raiserror('Creating procedure sp_vupgrade_publisherdb', 0,1) go create procedure sp_vupgrade_publisherdb @ver_old int, @ver_retention int AS declare @default_name sysname if exists (select name from sysobjects where name='syspublications') begin if @ver_old < @ver_retention begin update syspublications set retention = 72 if @@error<>0 return (1) end -- drop default_access column if exists (select * from syscolumns where id = object_id('syspublications') and name = 'default_access') begin alter table syspublications drop column default_access end end if exists (select name from sysobjects where name='sysmergepublications') begin alter table sysmergearticles alter column resolver_info nvarchar(255) NULL if @@ERROR <> 0 return 1 if @ver_old < @ver_retention begin update sysmergepublications set retention = 60 if @@error<>0 return (1) end -- drop default_access column if exists (select * from syscolumns where id = object_id('sysmergepublications') and name = 'default_access') begin -- Get the name of the default associated with default_access and then -- drop it select @default_name = null select @default_name = object_name(constid) from sysconstraints where id = object_id('sysmergepublications') and col_name(id, colid) = N'default_access' if @default_name is not null begin -- Drop the default exec (N'alter table sysmergepublications drop constraint ' + @default_name) end alter table sysmergepublications drop column default_access end end GO exec dbo.sp_MS_marksystemobject sp_vupgrade_publisherdb go grant execute on dbo.sp_vupgrade_publisherdb to public 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 */ begin declare @retcode int declare @profile_id int -- Drop and regenerate agent parameters and associated values -- from system profiles. -- select @profile_id = 1 while (@profile_id < 8) begin exec @retcode = dbo.sp_drop_agent_parameter @profile_id if (@retcode = 1) return (1) exec @retcode = dbo.sp_generate_agent_parameter @profile_id if (@retcode = 1) return (1) select @profile_id = @profile_id + 1 end /* create MSdatatype_mappings table */ IF NOT EXISTS (SELECT * FROM msdb..sysobjects WHERE name = 'MSdatatype_mappings' and xtype = 'U') begin 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 end return (0) end go exec dbo.sp_MS_marksystemobject sp_vupgrade_replmsdb 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 but db on server is not published; strip out replication tables directly exec dbo.sp_MSdrop_pub_tables -- deleting table is all the cleanup we can do select @remove_repl = 0 end -- publishing db check : merge if ( exists( select * from sysobjects where name = 'sysmergepublications' ) -- exists( select * from sysmergepublications ) and not exists( select * from master..sysdatabases where name = @db_orig and category & @db_mergbit = @db_mergbit ) -- preserve subscription only db restored to same server/db pair and ( @remove_repl = 1 ) ) begin -- merge publications but db on server is not published; strip out replication tables directly exec dbo.sp_MSdrop_mergesystables -- deleting table is all the cleanup we can do select @remove_repl = 0 end if ( @repl_installed = 1 ) and ( @remove_repl = 1 ) exec dbo.sp_removedbreplication @db_curr end go exec dbo.sp_MS_marksystemobject sp_restoredbreplication go raiserror('Creating procedure sp_MSget_publisher_rpc', 0,1) GO CREATE PROCEDURE sp_MSget_publisher_rpc @trigger_id int, @connect_string nvarchar(2000) output AS SET NOCOUNT ON declare @publisher sysname declare @publisher_db sysname declare @login sysname declare @password sysname declare @security_mode int declare @object_id int declare @retcode int -- Make sure this proc is called from the trigger. -- Better to use object_id if owner name is passed in. if trigger_nestlevel(@trigger_id) = 0 begin raiserror(14126, 16, -1) return (1) -- current user does not have insert permission to underlying table end -- Get security from property table, if nothing find, the rpc will fail. IF EXISTS (select * from sysobjects where name = 'MSsubscription_properties' and type = 'U') begin select @login = publisher_login, @password = publisher_password, @security_mode = publisher_security_mode, @publisher = o.publisher, @publisher_db = o.publisher_db from MSsubscription_properties p, MSreplication_objects o where o.object_name = object_name(@trigger_id) and UPPER(p.publisher) = UPPER(o.publisher) and p.publisher_db = p.publisher_db and p.publication = o.publication EXEC @retcode = master.dbo.xp_repl_encrypt @password OUTPUT IF @@error <> 0 OR @retcode <> 0 return 1 end else begin -- RPC security info invalid raiserror(21079, 16, -1) return(1) end if @security_mode = 2 -- 2 = use sysservers begin select @connect_string = null end else begin if @login is null begin -- RPC security info invalid raiserror(21079, 16, -1) return(1) end if @password is null select @password = N'' -- Names containing space in connection string is automatically enabled. -- [] and ' are not recoginized by opendatasource -- Note ';' in names in connection string will mess things up. select @connect_string = 'SERVER=' + @publisher + ';UID=' + @login + ';PWD=' + @password + ';' end GO raiserror('Creating procedure sp_link_publication', 0,1) GO CREATE PROCEDURE sp_link_publication @publisher sysname, -- publishing server name @publisher_db sysname, -- publishing database name. If NULL then same as current db @publication sysname, -- publication name @security_mode int, -- 0 = standard; 2 = static linked server entry @login sysname = NULL, @password sysname = NULL AS set nocount on declare @retcode int -- Security Check EXEC @retcode = dbo.sp_MSreplcheck_subscribe IF @@ERROR <> 0 or @retcode <> 0 RETURN(1) -- Parameter check: @security_mode if @security_mode <> 0 and @security_mode <> 2 begin RAISERROR(21055, 16, -1, '@security_mode','sp_link_publication') RETURN (1) end if @security_mode = 2 and not exists (select * from master..sysservers where UPPER(srvname) = UPPER(@publisher)) begin declare @len int select @len = len(@publisher) * 2 RAISERROR(7202, 16, -1, @len ,@publisher) RETURN (1) end IF @password = N'' select @password = NULL /* ** 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 return 1 -- Encrypt the password EXEC @retcode = master.dbo.xp_repl_encrypt @password OUTPUT IF @@error <> 0 OR @retcode <> 0 return 1 IF NOT EXISTS (select * from MSsubscription_properties where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication) BEGIN INSERT INTO MSsubscription_properties (publisher, publisher_db, publication, publication_type, publisher_login,publisher_password, publisher_security_mode, distributor, distributor_login, distributor_password, distributor_security_mode) values (@publisher, @publisher_db, @publication, 0, @login, @password, @security_mode, NULL, NULL, NULL, 1) END ELSE BEGIN update MSsubscription_properties set publisher_login = @login, publisher_password = @password, publisher_security_mode = @security_mode where UPPER(publisher) = UPPER(@publisher) and publisher_db = @publisher_db and publication = @publication END 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 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 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 exec dbo.sp_MS_marksystemobject sp_MScreate_sub_tables go raiserror('Creating procedure sp_MS_replication_installed', 0,1) GO CREATE PROCEDURE sp_MS_replication_installed as set nocount on declare @isinstalled int select @isinstalled = 0 create table #keyvalues (keyvalue nvarchar(255) NOT NULL, keyvaluedata nvarchar(255) null) insert into #keyvalues exec master..xp_regenumvalues 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\Replication' if @@ERROR <> 0 begin drop table #keyvalues return (-1) end select @isinstalled = convert (int, (select keyvaluedata from #keyvalues where keyvalue = N'IsInstalled')) drop table #keyvalues if (@isinstalled is null or @isinstalled = 0) begin raiserror (21028, 16, -1) return (0) end return (1) go exec dbo.sp_MS_marksystemobject sp_MS_replication_installed go raiserror('Creating procedure sp_MSunc_to_drive', 0,1) GO CREATE PROCEDURE sp_MSunc_to_drive ( @unc_path nvarchar(255), @local_server sysname, @local_path nvarchar(255) output ) AS SET NOCOUNT ON declare @pattern nvarchar(150) select @pattern = N'\\' + upper(@local_server) + N'\' if charindex(@pattern, upper(substring(@unc_path, 1, len(@pattern)))) <> 0 and charindex(N'$\', substring(@unc_path, len(@pattern)+2, 2))<>0 select @local_path = substring(@unc_path, len(@pattern) + 1, 1) + N':' + substring(@unc_path, len(@pattern) + 3, len(@unc_path) - len(@pattern) -1) else select @local_path = @unc_path GO exec dbo.sp_MS_marksystemobject sp_MSunc_to_drive go raiserror('Creating procedure sp_MSrepl_linkedservers_rowset', 0,1) GO create proc sp_MSrepl_linkedservers_rowset @srvname sysname as select SVR_NAME = srvname, SVR_PRODUCT = srvproduct, SVR_PROVIDERNAME = providername, SVR_DATASOURCE = datasource, SVR_PROVIDERSTRING = providerstring, SVR_LOCATION = location, SVR_CATALOG = catalog from master.dbo.sysservers where UPPER(srvname) = UPPER(@srvname) and isnull(providername,' ') <> ' ' and ( isnull(datasource, ' ') <> ' ' or isnull(location, ' ') <> ' ' or isnull(providerstring, ' ') <> ' ' or isnull(catalog, ' ') <> ' ' ) order by 1 go exec dbo.sp_MS_marksystemobject sp_MSrepl_linkedservers_rowset go raiserror('Creating procedure sp_MSget_qualified_name', 0,1) GO CREATE PROCEDURE sp_MSget_qualified_name ( @object_id int, @qualified_name nvarchar(512) output )AS select @qualified_name = quotename(user_name(OBJECTPROPERTY(@object_id,'OwnerId'))) + N'.' + quotename(object_name(@object_id)) GO exec dbo.sp_MS_marksystemobject sp_MSget_qualified_name go raiserror('Creating procedure sp_MSdrop_object', 0,1) GO CREATE PROCEDURE sp_MSdrop_object ( @object_id int = NULL, @object_name sysname = NULL, @object_owner sysname = NULL ) AS SET NOCOUNT ON declare @cmd nvarchar(1000) if @object_name is not null begin declare @owner_id int if @object_owner is null select @owner_id = user_id() else select @owner_id = user_id(@object_owner) select @object_id = id from sysobjects where name = @object_name and uid = @owner_id end if @object_id is not null begin exec dbo.sp_MSget_qualified_name @object_id, @cmd output if objectproperty(@object_id, 'IsTable') = 1 select @cmd = 'drop table ' + @cmd else if objectproperty(@object_id, 'IsProcedure') = 1 select @cmd = 'drop procedure ' + @cmd else if objectproperty(@object_id, 'IsTrigger') = 1 select @cmd = 'drop trigger ' + @cmd else if objectproperty(@object_id, 'IsView') = 1 select @cmd = 'drop view ' + @cmd end exec (@cmd) if @@error <> 0 return(1) 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 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 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 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 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 raiserror('Creating procedure sp_MSunregistersubscription', 0,1) go CREATE PROCEDURE sp_MSunregistersubscription @publisher sysname = NULL, @publisher_db sysname = NULL, @publication sysname = NULL, @subscriber sysname = NULL, @subscriber_db sysname = NULL AS /* ** Drop the corresponding registry entry for MobileSync */ declare @subscription_name nvarchar(1000) declare @regkey nvarchar(1000) declare @retcode int declare @keyexist int 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 create table #keyexist (keyexist int) insert into #keyexist EXECUTE master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', @regkey select @keyexist = keyexist from #keyexist drop table #keyexist if @keyexist = 1 begin EXECUTE @retcode = master.dbo.xp_regdeletekey 'HKEY_LOCAL_MACHINE', @regkey if @@error <> 0 OR @retcode <> 0 return 1 end return 0 GO raiserror('Creating procedure sp_MSget_jobstate', 0,1) go -- Procedure sp_MSget_jobstate -- The proc takes a specific Job ID and returns the Job State of the job -- Returns a row with one column job_state -- Returns a row with NULL if job does not exist -- CREATE PROCEDURE sp_MSget_jobstate @job_id UNIQUEIDENTIFIER AS BEGIN DECLARE @is_sysadmin INT DECLARE @job_owner sysname DECLARE @job_state INT DECLARE @job_id_as_char VARCHAR(36) SET NOCOUNT ON CREATE TABLE #xp_results (job_id UNIQUEIDENTIFIER NOT NULL, last_run_date INT NOT NULL, last_run_time INT NOT NULL, next_run_date INT NOT NULL, next_run_time INT NOT NULL, next_run_schedule_id INT NOT NULL, requested_to_run INT NOT NULL, -- BOOL request_source INT NOT NULL, request_source_id sysname NULL, running INT NOT NULL, -- BOOL current_step INT NOT NULL, current_retry_attempt INT NOT NULL, job_state INT NOT NULL) -- Need a job_id if (@job_id IS NULL) BEGIN SELECT @job_id_as_char = CONVERT(VARCHAR(36), @job_id) RAISERROR(14262, -1, -1, '@job_id', @job_id_as_char) RETURN(1) -- Failure END -- Capture job execution information (for local jobs only since that's all SQLServerAgent caches) SELECT @is_sysadmin = ISNULL(IS_SRVROLEMEMBER(N'sysadmin'), 0) SELECT @job_owner = suser_sname(suser_sid()) INSERT INTO #xp_results EXECUTE master.dbo.xp_sqlagent_enum_jobs @is_sysadmin, @job_owner -- Select the job state of the job in question SELECT @job_state = job_state FROM #xp_results WHERE @job_id = job_id -- Error if we have no rows selected if (@job_state IS NULL) BEGIN SELECT @job_id_as_char = CONVERT(VARCHAR(36), @job_id) RAISERROR(14262, -1, -1, '@job_id', @job_id_as_char) RETURN(1) -- Failure END ELSE SELECT @job_state -- All done DROP TABLE #xp_results RETURN(0) -- Success END GO raiserror('Creating procedure sp_MSrepl_isdbowner', 0,1) go CREATE PROCEDURE sp_MSrepl_isdbowner @dbname nvarchar(255) AS BEGIN SET NOCOUNT ON DECLARE @retcode int DECLARE @cmd nvarchar(255) DECLARE @isdbowner int SELECT @retcode = databaseproperty(@dbname, 'issingleuser') IF (@retcode = 1) BEGIN /* Database is in single user mode, so if another spid already connected, ** do not attempt to connect. */ IF EXISTS (SELECT spid FROM sysprocesses WHERE dbid = db_id(@dbname)) RETURN 0 END SELECT @retcode = has_dbaccess(@dbname) IF (@retcode IS NULL) OR (@retcode = 0) BEGIN /* ** Either no access or database not found ** No need to go further */ RETURN 0 END SELECT @cmd = 'USE ' + quotename(@dbname) + ' SELECT @isdbowner = is_member(''db_owner'')' EXEC sp_executesql @cmd, N'@isdbowner int output', @isdbowner output RETURN isnull(@isdbowner, 0) END GO raiserror('Creating procedure sp_MSscript_pkvar_assignment', 0,1) go create procedure sp_MSscript_pkvar_assignment @objid int, @columns binary(32), @indent int = 0, @identity_col sysname = NULL, -- Not null value used by trigger scripting @ts_col sysname = NULL -- Not null value used by trigger scripting as -- This stored procedure will assign the '_old' var to new var -- based on @bitmap. This is to avoid using case statement -- in the where clause in the synctran pub proc, which -- will cause a table scan. -- See bug 50236 declare @cmd nvarchar(4000) declare @spacer nvarchar(20) declare @indkey int declare @indid int declare @this_col int declare @col sysname declare @qualname nvarchar(512) declare @column nvarchar(255) declare @key sysname declare @src_cols int select @spacer = N'select ', @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 exec dbo.sp_MSflush_command @cmd output, 1, @indent 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 = @objid, @columns = @columns, @key = @key, @colpos = @col output, @this_col = @this_col output select @indkey = @indkey + 1 if @key in (@identity_col, @ts_col) continue select @cmd = @spacer + N'@c' + convert(nvarchar(10), @this_col) -- Get the new values for the columns in primary key. exec dbo.sp_MSget_synctran_column @ts_col = null, @op_type = null , -- 'ins, 'upd', 'del' @is_new = null, @primary_key_bitmap = null, @colname = null, @this_col = @this_col, @column = @column output, @from_proc = 0, @coltype = null, @type = 'pk_var' select @cmd = @cmd + N' = ' + @column select @spacer = ', ' -- flush command if necessary exec dbo.sp_MSflush_command @cmd output, 1, @indent end end go raiserror('Creating procedure sp_MSget_publication_from_taskname', 0,1) go create procedure sp_MSget_publication_from_taskname @taskname sysname, @publisher sysname, @publisherdb sysname, @publication sysname OUTPUT as declare @value sysname declare @value2 sysname declare @position INT select @publication = NULL -- Parse out publication name from the task name "publisher_publisherdb_publication_number" -- Expect publisher name if charindex(@publisher, @taskname) <> 1 begin return 1 end -- Eat up the publisher name select @value = stuff(@taskname, 1, len(@publisher), N'') -- Expect '_' + publisherdb + '_' select @value2 = N'_' + @publisherdb + N'_' if charindex(@value2, @value) <> 1 begin return 1 end -- Eat up '_' + publisherdb + '_' select @value = stuff(@value, 1, LEN(@publisherdb) + 2, N'') -- Reverse the string in the hope of finding the first '_' -- from the right which denotes the end of the publication -- name. The number at the end should not contain '_' select @value2 = reverse(@value) select @position = charindex(N'_', @value2) if @position < 2 begin return 1 end select @publication = left(@value, len(@value) - @position) return 0 go EXEC dbo.sp_MS_marksystemobject sp_MSget_publication_from_taskname go raiserror('Creating procedure sp_MSrepl_check_server', 0,1) go CREATE PROCEDURE sp_MSrepl_check_server ( @srvname sysname, @check_distdb bit = 0 ) AS -- This sp is called by sp_dropserver to check if the server is in use by replication. declare @subscriber_bit smallint declare @distributor_bit smallint declare @retcode int declare @proc nvarchar(255) declare @dbname sysname -- Intialize select @distributor_bit = 8 select @subscriber_bit = 4 if @check_distdb = 0 begin -- Check to see if the server is marked as a Distributor if exists (select * from sysservers where UPPER(srvname) = UPPER(@srvname) and srvstatus & @distributor_bit <> 0) begin raiserror(20581, 16, -1, @srvname) return (1) end -- Check to see if the server is marked as a subscriber if exists (select * from sysservers where UPPER(srvname) = UPPER(@srvname) and srvstatus & @subscriber_bit <> 0) begin raiserror(20583, 16, -1, @srvname) return (1) end -- Check to see if the server is a dist publisher if object_id('msdb.dbo.MSdistpublishers') is not null begin if exists (select * from msdb.dbo.MSdistpublishers where UPPER(name) = UPPER(@srvname)) begin raiserror(20582, 16, -1, @srvname) return (1) end end -- Check to see if the server is in use as a subscriber in the distribution dbs. if object_id('msdb.dbo.MSdistributiondbs') is not null begin declare hCForEachDb CURSOR LOCAL FAST_FORWARD FOR select name from msdb.dbo.MSdistributiondbs FOR READ ONLY open hCForEachDb fetch hCForEachDb into @dbname /* Loop for each database */ while (@@fetch_status >= 0) begin select @proc = quotename(@dbname) + '.dbo.sp_MSrepl_check_server' exec @retcode = @proc @srvname = @srvname, @check_distdb = 1 if @retcode <> 0 or @@error <> 0 return (1) fetch hCForEachDb into @dbname end /* while FETCH_SUCCESS */ end end else begin if object_id('MSsubscriber_info') is not null begin declare @publisher sysname select @publisher = publisher from MSsubscriber_info sub where UPPER(subscriber) = UPPER(@srvname) if @publisher is not null begin raiserror(20584, 16, -1, @srvname, @publisher) return (1) end end end GO EXEC dbo.sp_MS_marksystemobject sp_MSrepl_check_server go grant execute on dbo.sp_MSrepl_check_server to public go raiserror('Creating procedure sp_MSreset_synctran_bit', 0,1) go CREATE PROCEDURE sp_MSreset_synctran_bit ( @owner sysname, @table sysname )AS declare @qualified_name nvarchar(300) declare @synctran_bit int select @synctran_bit = 256 if @owner = N'' select @qualified_name = @table else select @qualified_name = quotename(@owner) + '.' + quotename(@table) -- Unmark synctran bit update sysobjects set replinfo = replinfo & ~@synctran_bit where id = object_id(@qualified_name) and (replinfo & @synctran_bit) <> 0 IF @@ERROR <> 0 return(1) return(0) GO EXEC dbo.sp_MS_marksystemobject sp_MSreset_synctran_bit go grant execute on dbo.sp_MSreset_synctran_bit to public go EXEC dbo.sp_MS_marksystemobject sp_MSget_jobstate GO exec dbo.sp_MS_marksystemobject sp_MSunc_to_drive go exec dbo.sp_MS_marksystemobject sp_MSrepl_isdbowner go grant execute on dbo.sp_MSget_qualified_name to public go dump tran master with no_log go grant execute on dbo.sp_helpreplicationoption to public go grant execute on dbo.sp_addpullsubscription to public go grant execute on dbo.sp_addpullsubscription_agent to public go grant execute on dbo.sp_droppullsubscription to public go grant execute on dbo.sp_helppullsubscription to public go grant execute on dbo.sp_addpullsubscription to public go grant execute on dbo.sp_addpullsubscription_agent to public go grant execute on dbo.sp_droppullsubscription to public go grant execute on dbo.sp_helppullsubscription to public go grant execute on dbo.sp_helpreplicationdboption to public go grant exec on dbo.sp_addsynctriggers to public go grant exec on dbo.sp_MScheck_agent_instance to public go grant exec on dbo.sp_get_distributor to public go grant exec on dbo.sp_table_validation to public grant exec on dbo.sp_addmergepullsubscription to public grant exec on dbo.sp_dropmergepullsubscription to public grant exec on dbo.sp_changemergepullsubscription to public grant exec on dbo.sp_helpmergepullsubscription to public grant exec on dbo.sp_addmergepullsubscription_agent to public go grant exec on dbo.sp_helpsubscription_properties to public grant exec on dbo.sp_change_subscription_properties to public grant exec on dbo.sp_MSget_publisher_rpc to public grant exec on dbo.sp_MSreplcheck_subscribe to public grant exec on dbo.sp_link_publication to public grant exec on dbo.sp_MS_replication_installed to public grant exec on dbo.sp_MSrepl_linkedservers_rowset to public grant exec on dbo.sp_MScreate_sub_tables to public grant exec on dbo.sp_MSget_jobstate to public go grant exec on dbo.sp_MSrepl_isdbowner to public grant exec on dbo.sp_MSscript_pkvar_assignment to public go grant exec on dbo.sp_MSreplraiserror to public grant exec on dbo.sp_check_sync_trigger to public grant exec on dbo.sp_check_for_sync_trigger to public go grant execute on dbo.sp_MSscript_where_clause to public grant execute on dbo.sp_MSscript_params to public grant execute on dbo.sp_MSscript_begintrig1 to public grant execute on dbo.sp_MSscript_begintrig2 to public grant execute on dbo.sp_MSscript_endtrig to public grant execute on dbo.sp_MSscript_trigger_variables to public grant execute on dbo.sp_MSscript_trigger_assignment to public grant execute on dbo.sp_MSscript_trigger_fetch_statement to public grant execute on dbo.sp_MSscript_trigger_exec_rpc to public grant execute on dbo.sp_MSscript_trigger_update_checks to public grant execute on dbo.sp_MSscript_trigger_updates to public grant execute on dbo.sp_MSscript_singlerow_trigger to public grant execute on dbo.sp_MSscript_multirow_trigger to public grant execute on dbo.sp_MSscript_sync_ins_trig to public grant execute on dbo.sp_MSscript_sync_upd_trig to public grant execute on dbo.sp_MSscript_sync_del_trig to public grant execute on dbo.sp_MSscript_pkvar_assignment to public grant execute on dbo.sp_MSreplcheck_pull to public go dump tran master with no_log go sp_configure 'allow updates',0 go reconfigure with override go print '' print 'Checking objects created by replsys.sql.' go --obsolete exec dbo.sp_check_objects 'repl' exec dbo.sp_MS_upd_sysobj_category 2 --set sysobjects.category | 2 based on crdate. go print '' print 'replsys.sql completed successfully.' go dump tran master with no_log go checkpoint go -- - -----