/* ** repltran.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. */ use master go dump tran master with no_log go exec dbo.sp_configure 'update',1 go reconfigure with override go set ANSI_NULLS off go -- sp_MS_upd_sysobj_category is obsolete, use sp_MS_marksystemobject instead -- exec dbo.sp_MS_upd_sysobj_category 1 --Capture time for use at the end -- go /* ** Drop the stored procedures in this script using the old dropping SP ** and then drop itself */ if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSdrop_repltran') begin exec dbo.sp_MSdrop_repltran drop procedure sp_MSdrop_repltran end /* ** Create stored procedures to drop the stored procedures ** created by this script */ print '' print 'Creating procedure sp_MSdrop_repl_tran.' go create procedure sp_MSdrop_repltran as if exists( select * from sysobjects where type = 'P ' and name = 'sp_MSsetfilterparent' ) drop procedure sp_MSsetfilterparent if exists( select * from sysobjects where type = 'P ' and name = 'sp_MSdoesfilterhaveparent' ) drop procedure sp_MSdoesfilterhaveparent if exists( select * from sysobjects where type = 'P ' and name = 'sp_MSsetfilteredstatus' ) drop procedure sp_MSsetfilteredstatus if exists ( select * from sysobjects where type = 'P ' and name = 'sp_MSreplsup_table_has_pk' ) DROP PROC sp_MSreplsup_table_has_pk if exists (select * from sysobjects where type = 'P ' and name = 'sp_MScreate_pub_tables') drop procedure sp_MScreate_pub_tables if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSdrop_expired_subscription') drop procedure sp_MSdrop_expired_subscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_replsync') drop procedure sp_replsync if exists (select * from sysobjects where type = 'P ' and name = 'sp_enumfullsubscribers') drop procedure sp_enumfullsubscribers if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSaddexecarticle') drop procedure sp_MSaddexecarticle dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_addarticle') drop procedure sp_addarticle if exists (select * from sysobjects where type = 'P ' and name = 'sp_articlecolumn') drop procedure sp_articlecolumn dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_articlefilter') drop procedure sp_articlefilter if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSarticletextcol') drop procedure sp_MSarticletextcol dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_MStextcolstatus') drop procedure sp_MStextcolstatus if exists (select * from sysobjects where type = 'P ' and name = 'sp_articleview') drop procedure sp_articleview dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_addpublication') drop procedure sp_addpublication dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_addsubscription') drop procedure sp_addsubscription IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P ' AND name = 'sp_changearticle') DROP PROCEDURE sp_changearticle dump tran master with no_log IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P ' AND name = 'sp_changepublication') DROP PROCEDURE sp_changepublication IF EXISTS (SELECT * FROM sysobjects WHERE type = 'P ' AND name = 'sp_changesubscription') DROP PROCEDURE sp_changesubscription dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_MShcchangesubstatus1') drop procedure sp_MShcchangesubstatus1 if exists (select * from sysobjects where type = 'P ' and name = 'sp_MShcchangesubstatus2') drop procedure sp_MShcchangesubstatus2 if exists (select * from sysobjects where type = 'P ' and name = 'sp_MShcchangesubstatus3') drop procedure sp_MShcchangesubstatus3 dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_changesubstatus') drop procedure sp_changesubstatus if exists (select * from sysobjects where type = 'P ' and name = 'sp_droparticle') drop procedure sp_droparticle dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_droppublication') drop procedure sp_droppublication if exists (select * from sysobjects where type = 'P ' and name = 'sp_dropsubscription') drop procedure sp_dropsubscription dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_helparticle') drop procedure sp_helparticle dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_helparticlecolumns') drop procedure sp_helparticlecolumns if exists (select * from sysobjects where type = 'P ' and name = 'sp_helppublication') drop procedure sp_helppublication if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSaddpub_snapshot') drop procedure sp_MSaddpub_snapshot dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_helpsubscription') drop procedure sp_helpsubscription if exists (select * from sysobjects where type = 'P ' and name = 'sp_subscribe') drop procedure sp_subscribe if exists (select * from sysobjects where type = 'P ' and name = 'sp_unsubscribe') drop procedure sp_unsubscribe if exists (select * from sysobjects where type = 'P ' and name = 'sp_refreshsubscriptions') drop procedure sp_refreshsubscriptions dump tran master with no_log if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSpublishdb') drop procedure sp_MSpublishdb if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSactivate_auto_sub') drop procedure sp_MSactivate_auto_sub if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSget_synctran_commands') drop procedure sp_MSget_synctran_commands if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSdrop_pub_tables') begin -- Don't drop the system tables here. repltran.sql should not -- delete any data in the master database (see bug 34219). -- exec dbo.sp_MSdrop_pub_tables drop procedure sp_MSdrop_pub_tables end -- SyncTran if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSis_col_replicated') drop procedure sp_MSis_col_replicated if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSis_pk_col') drop procedure sp_MSis_pk_col if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_insert_statement') drop procedure sp_MSscript_insert_statement if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_update_statement') drop procedure sp_MSscript_update_statement if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_delete_statement') drop procedure sp_MSscript_delete_statement if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_beginproc') drop procedure sp_MSscript_beginproc if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_security') drop procedure sp_MSscript_security if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_endproc') drop procedure sp_MSscript_endproc if exists (select * from sysobjects where type = 'P ' and name = 'sp_MStable_not_modifiable') drop procedure sp_MStable_not_modifiable if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_sync_ins_proc') drop procedure sp_MSscript_sync_ins_proc if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_sync_upd_proc') drop procedure sp_MSscript_sync_upd_proc if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSscript_sync_del_proc') drop procedure sp_MSscript_sync_del_proc if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSgen_sync_tran_procs') drop procedure sp_MSgen_sync_tran_procs if exists (select * from sysobjects where type = 'P ' and name = 'sp_MSmark_proc_norepl') drop procedure sp_MSmark_proc_norepl if exists (select * from sysobjects where type = 'P ' and name = 'sp_articlesynctranprocs') drop procedure sp_articlesynctranprocs if exists (select * from sysobjects where type = 'P ' and name = 'sp_reinitsubscription') drop procedure sp_reinitsubscription dump tran master with no_log if exists( select * from sysobjects where type = 'P ' and name = N'sp_getarticlepkcolbitmap') begin drop procedure sp_getarticlepkcolbitmap end if exists( select * from sysobjects where type = 'P ' and name = N'sp_gettypestring' ) begin drop procedure sp_gettypestring end if exists( select * from sysobjects where type = 'P ' and name = N'sp_isarticlecolbitset' ) begin drop procedure sp_isarticlecolbitset end if exists( select * from sysobjects where type = 'P ' and name = N'sp_scriptpkwhereclause' ) begin drop procedure sp_scriptpkwhereclause end if exists( select * from sysobjects where type = 'P ' and name = N'sp_scriptupdateparams' ) begin drop procedure sp_scriptupdateparams end if exists( select * from sysobjects where type = 'P ' and name = N'sp_scriptinsproc' ) begin drop procedure sp_scriptinsproc end if exists( select * from sysobjects where type = 'P ' and name = N'sp_scriptdelproc' ) begin drop procedure sp_scriptdelproc end if exists( select * from sysobjects where type = 'P ' and name = N'sp_scriptupdproc' ) begin drop procedure sp_scriptupdproc end if exists ( select * from sysobjects where type = 'P ' and name = 'sp_scriptmappedupdproc' ) begin drop procedure sp_scriptmappedupdproc end if exists ( select * from sysobjects where type = 'P ' and name = 'sp_fetchshowcmdsinput' ) begin drop procedure sp_fetchshowcmdsinput end if exists ( select * from sysobjects where type = 'P ' and name = 'sp_replshowcmds' ) begin drop procedure sp_replshowcmds end if exists ( select * from sysobjects where type = 'P ' and name = 'sp_publication_validation' ) begin drop procedure sp_publication_validation end if exists ( select * from sysobjects where type = 'P ' and name = 'sp_article_validation' ) begin drop procedure sp_article_validation end if exists ( select * from sysobjects where type = 'P ' and name = 'sp_MSdrop_6x_replication_agent' ) begin drop procedure sp_MSdrop_6x_replication_agent end if exists ( select * from sysobjects where type = 'P ' and name = 'sp_script_synctran_commands' ) begin drop procedure sp_script_synctran_commands end dump tran master with no_log go EXEC dbo.sp_MS_marksystemobject sp_MSdrop_repltran GO EXEC dbo.sp_MSdrop_repltran GO /* Create and execute dbo.sp_MSdrop_pub_tables */ print '' print 'Creating procedure sp_MSdrop_pub_tables' go CREATE PROCEDURE sp_MSdrop_pub_tables AS begin tran save TRAN sp_drop_central_pub_tables /* drop 'sysarticles' */ IF exists (select * from sysobjects where name = 'sysarticles') BEGIN DROP TABLE sysarticles IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_drop_central_pub_tables commit tran end RETURN(1) END END /* drop 'syspublications' */ IF exists (select * from sysobjects where name = 'syspublications') BEGIN DROP TABLE syspublications IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_drop_central_pub_tables commit tran end RETURN(1) END END /* drop 'syssubscriptions' */ IF exists (select * from sysobjects where name = 'syssubscriptions') BEGIN DROP TABLE syssubscriptions IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_drop_central_pub_tables commit tran end RETURN(1) END END -- SyncTran /* drop 'sysarticleupdates' */ IF exists (select * from sysobjects where name = 'sysarticleupdates') BEGIN DROP TABLE sysarticleupdates IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_drop_central_pub_tables commit tran end RETURN(1) END END -- end SyncTran COMMIT TRAN GO EXEC dbo.sp_MS_marksystemobject sp_MSdrop_pub_tables GO dump tran master with no_log go --print '' --print 'Executing procedure dbo.sp_MSdrop_pub_tables.' --go --exec dbo.sp_MSdrop_pub_tables --go --dump tran master with no_log --go /* Create and execute dbo.sp_MScreate_pub_tables */ dump tran master with no_log go print '' print 'Creating procedure sp_MScreate_pub_tables' go CREATE PROCEDURE sp_MScreate_pub_tables AS DECLARE @fError int SELECT @fError = 0 -- enable 'create tables as pseudo system tables -- sp_MS_upd_sysobj_category is obsolete, use sp_MS_marksystemobject instead -- exec dbo.sp_MS_upd_sysobj_category 1 /* ** Msg 226, Level 16, State 9 ** CREATE TABLE system-table command not allowed within multi-statement transaction. */ /* BEGIN TRAN sp_create_central_pub_tables */ /* Creating 'sysarticles' */ IF not exists (select * from sysobjects where name = 'sysarticles') BEGIN create table dbo.sysarticles ( artid int identity NOT NULL, columns varbinary(32) NULL, creation_script nvarchar(255) NULL, del_cmd nvarchar(255) NULL, description nvarchar(255) NULL, dest_table sysname NOT NULL, filter int NOT NULL, filter_clause ntext NULL, ins_cmd nvarchar(255) NULL, name sysname NOT NULL, objid int NOT NULL, pubid int NOT NULL, pre_creation_cmd tinyint NOT NULL, status tinyint NOT NULL, sync_objid int NOT NULL, type tinyint NOT NULL, upd_cmd nvarchar(255) NULL, schema_option binary(8) NULL, dest_owner sysname NULL ) EXEC dbo.sp_MS_marksystemobject 'sysarticles' IF @@error<>0 BEGIN GOTO ERROR END create unique nonclustered index unc1sysarticles on sysarticles(artid, pubid) IF @@error<>0 BEGIN GOTO ERROR END END /* Creating 'syspublications' */ IF NOT EXISTS (select * from sysobjects where name = 'syspublications') BEGIN CREATE TABLE dbo.syspublications ( description nvarchar(255) NULL, name sysname NOT NULL, pubid int identity NOT NULL, repl_freq tinyint NOT NULL, status tinyint NOT NULL, sync_method tinyint NOT NULL, snapshot_jobid binary(16) NULL, independent_agent bit NOT NULL, immediate_sync bit NOT NULL, enabled_for_internet bit NOT NULL, allow_push bit NOT NULL, allow_pull bit NOT NULL, allow_anonymous bit NOT NULL, immediate_sync_ready bit NOT NULL, -- SyncTran allow_sync_tran bit NOT NULL, autogen_sync_procs bit NOT NULL, retention int NULL ) EXEC dbo.sp_MS_marksystemobject 'syspublications' IF @@ERROR <> 0 BEGIN GOTO ERROR END create unique nonclustered index unc1syspublications on syspublications (pubid) IF @@ERROR <> 0 BEGIN GOTO ERROR END create unique nonclustered index unc2syspublications on syspublications (name) IF @@ERROR <> 0 BEGIN GOTO ERROR END END /* Creating 'syssubscriptions' */ IF not exists (select * from sysobjects where name = 'syssubscriptions') BEGIN CREATE TABLE dbo.syssubscriptions ( artid int NOT NULL, srvid smallint NOT NULL, dest_db sysname NOT NULL, status tinyint NOT NULL, sync_type tinyint NOT NULL, login_name sysname NOT NULL, subscription_type int NOT NULL, distribution_jobid binary(16) NULL, timestamp NOT NULL, -- SyncTran update_mode tinyint NOT NULL, -- 0 (read only), 1 (Sync Tran), ... loopback_detection bit NOT NULL ) EXEC dbo.sp_MS_marksystemobject 'syssubscriptions' IF @@ERROR <> 0 BEGIN GOTO ERROR END create unique nonclustered index unc1syssubscriptions on syssubscriptions (artid, srvid, dest_db) IF @@ERROR <> 0 BEGIN GOTO ERROR END END -- SyncTran /* Creating 'sysarticleupdates' */ IF not exists (select * from sysobjects where name = 'sysarticleupdates') BEGIN CREATE TABLE dbo.sysarticleupdates ( artid int NOT NULL, pubid int NOT NULL, sync_ins_proc int NOT NULL, -- ID of sproc handling Insert Sync Transactions sync_upd_proc int NOT NULL, -- ID of sproc handling Update Sync Transactions sync_del_proc int NOT NULL, autogen bit NOT NULL) -- ID of sproc handling Delete Sync Transactions IF @@ERROR <> 0 BEGIN GOTO ERROR END create unique nonclustered index unc1sysarticleupdates on sysarticleupdates (artid, pubid) IF @@ERROR <> 0 BEGIN GOTO ERROR END -- mark the index as a system object exec dbo.sp_MS_marksystemobject 'sysarticleupdates' IF @@ERROR <> 0 BEGIN GOTO ERROR END END -- end SyncTran CLEANUP: -- disable 'create tables as pseudo system tables -- sp_MS_upd_sysobj_category is obsolete, use sp_MS_marksystemobject instead -- exec dbo.sp_MS_upd_sysobj_category 2 RETURN( @fError ) ERROR: select @fError = 1 GOTO CLEANUP GO EXEC dbo.sp_MS_marksystemobject sp_MScreate_pub_tables GO dump tran master with no_log go /* ** Create replication stored procedures. ** Part 2: create all other stored procedures. */ create proc sp_MSsetfilterparent @filter_name sysname, @parent_id int as -- SQL SERVER 7.0 ONLY update sysobjects, set parent id = underlying -- object id declare @retcode int exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) BEGIN TRAN exec dbo.sp_replupdateschema @filter_name update sysobjects set parent_obj = @parent_id where id = object_id( @filter_name ) COMMIT TRAN go EXEC dbo.sp_MS_marksystemobject sp_MSsetfilterparent GO create proc sp_MSdoesfilterhaveparent @filter_id int as declare @retcode int exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) if exists ( select * from sysobjects where id = @filter_id and parent_obj <> 0 ) BEGIN return 1 END ELSE BEGIN return 0 END go EXEC dbo.sp_MS_marksystemobject sp_MSdoesfilterhaveparent GO create proc sp_MSsetfilteredstatus @object_id int as declare @qualified_name nvarchar(512) declare @retcode int exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) exec dbo.sp_MSget_qualified_name @object_id, @qualified_name output BEGIN TRANSACTION exec dbo.sp_replupdateschema @qualified_name if exists( select * from sysobjects where type = 'RF' and parent_obj = @object_id ) or exists( select * from sysarticles where objid = @object_id and ( upd_cmd like 'CALL%' OR upd_cmd like 'XCALL%' ) ) begin update sysobjects set replinfo = replinfo | 32 where id = @object_id end else begin update sysobjects set replinfo = replinfo & ~32 where id = @object_id end COMMIT TRANSACTION go EXEC dbo.sp_MS_marksystemobject sp_MSsetfilteredstatus GO CREATE PROCEDURE sp_MSreplsup_table_has_pk @tabid INT as IF NOT EXISTS (SELECT * FROM sysobjects WHERE parent_obj = @tabid AND xtype = 'PK') RETURN 0 ELSE RETURN 1 go EXEC dbo.sp_MS_marksystemobject sp_MSreplsup_table_has_pk GO CREATE PROCEDURE sp_replsync ( @publisher sysname, @publisher_db sysname, @publication sysname, @article sysname = '%' ) AS SET NOCOUNT ON RAISERROR (21023, 16, -1,'sp_replsync') RETURN(1) GO EXEC dbo.sp_MS_marksystemobject sp_replsync GO print '' print 'Creating procedure sp_enumfullsubscriber' go CREATE PROCEDURE sp_enumfullsubscribers ( @publication sysname = '%' /* The publication name */ ) AS /* ** Declarations. */ DECLARE @retcode int /* ** Security Check */ exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Parameter Check: @publication. ** Check to make sure that the publication exists and that it conforms ** to the rules for identifiers. */ IF @publication IS NOT NULL BEGIN IF @publication <> '%' BEGIN EXECUTE @retcode = dbo.sp_validname @publication IF @retcode <> 0 RETURN (1) END IF NOT EXISTS (SELECT * FROM syspublications WHERE name LIKE @publication) BEGIN RAISERROR (20026, 11, -1, @publication) RETURN (1) END END ELSE BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END /* ** Select all subscribers who subscribe to all articles in the desired ** publication. */ SELECT DISTINCT 'subscriber' = sv.srvname FROM syspublications p, sysarticles s, syssubscriptions ss, master..sysservers sv WHERE p.name LIKE @publication AND p.pubid = s.pubid AND s.artid = ss.artid AND ss.srvid = sv.srvid AND NOT EXISTS (SELECT * FROM sysarticles s2 WHERE s2.pubid = p.pubid AND NOT EXISTS (SELECT * FROM syssubscriptions ss2, master..sysservers sv2 WHERE s2.artid = ss2.artid AND ss2.srvid = sv2.srvid AND sv2.srvid = sv.srvid)) go EXEC dbo.sp_MS_marksystemobject sp_enumfullsubscribers GO print '' print 'Creating procedure sp_addpublication.' go CREATE PROCEDURE sp_addpublication ( @publication sysname, /* publication name */ @taskid int = 0, /* backward compatible */ @restricted nvarchar (10) = 'false', /* publication security */ @sync_method nvarchar(13) = 'native', /* (bcp) native, (bcp) character */ @repl_freq nvarchar(10) = 'continuous', /* continuous, snapshot */ @description nvarchar (255) = NULL, /* publication description */ @status nvarchar(8) = 'inactive', /* publication status; 0=inactive, 1=active */ @independent_agent nvarchar(5) = 'false', /* true or false */ @immediate_sync nvarchar(5) = 'false', /* true or false */ @enabled_for_internet nvarchar(5) = 'false', /* true or false */ @allow_push nvarchar(5) = 'true', /* true or false */ @allow_pull nvarchar(5) = 'false', /* true or false */ @allow_anonymous nvarchar(5) = 'false', /* true or false */ -- SyncTran @allow_sync_tran nvarchar(5) = 'false', /* true or false */ @autogen_sync_procs nvarchar(5) = 'true', /* auto gen sync tran procs per article */ @retention int = 72 /* over weekend - 3 days */ ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @retcode int /* return code value for procedure execution */ DECLARE @rfid tinyint /* identifier for replication frequency */ DECLARE @publish_bit smallint /* publication bit (flag) in sysobjects */ DECLARE @smid tinyint /* identifier for sync method */ DECLARE @statid tinyint /* status id based on @status */ DECLARE @subs_type_id tinyint /* subscription type id based on @subscription_type */ DECLARE @distributor sysname DECLARE @distribdb sysname DECLARE @distproc nvarchar (255) DECLARE @agentname nvarchar (40) DECLARE @dbname sysname DECLARE @mergepublish_bit smallint DECLARE @found int DECLARE @independent_agent_id bit DECLARE @immediate_sync_id bit DECLARE @enabled_for_internet_id bit DECLARE @allow_push_id bit DECLARE @allow_pull_id bit DECLARE @allow_anonymous_id bit DECLARE @pubid int declare @distgroup sysname -- SyncTran DECLARE @allow_sync_tran_id bit DECLARE @autogen_sync_procs_id bit select @allow_sync_tran_id = 0, @autogen_sync_procs_id = 0 -- end SyncTran declare @qv_replication varchar(10) declare @qv_replication_unlimited integer declare @qv_value_replication integer select @qv_replication = '2745196162', @qv_replication_unlimited = 0 /* ** The default value for TRAN publication is always 72 hours */ if @retention is NULL BEGIN RAISERROR(20081, 16, -1, 'retention') RETURN (1) END if @retention < 0 BEGIN RAISERROR (20050, 16, -1, 1) RETURN(1) END /* ** Setting retention period to 0 will cause the default value to be used. ** This is also the workaround for DMO bug #49491, where a 0 is incorrectly ** passed to stored procedure. */ if @retention = 0 select @retention = 72 SELECT @publish_bit = 32 SELECT @mergepublish_bit = 4 /* ** Security Check */ exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Check to see if the database has been activated for publication. */ IF (SELECT category & 1 FROM master..sysdatabases WHERE name = DB_NAME()) = 0 BEGIN RAISERROR (14013, 16, -1) RETURN (1) END IF @taskid <> 0 BEGIN -- No longer supported RAISERROR (21023, 16, -1,'@taskid') RETURN(1) END /* ** Parameter Check: @publication. ** The @publication name must conform to the rules for identifiers, ** and must not be the keyword 'all'. */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END exec @retcode = dbo.sp_MSreplcheck_name @publication if @@ERROR <> 0 or @retcode <> 0 return(1) IF LOWER (@publication) = 'all' BEGIN RAISERROR (14034, 16, -1) RETURN (1) END /* ** Check if the publication already exists. ** 1. Check transaction-level publications ** 2. Check merge publications */ IF EXISTS (SELECT * FROM syspublications WHERE name = @publication) BEGIN RAISERROR (14016, 16, -1, @publication) RETURN (1) END if (select category & @mergepublish_bit from master..sysdatabases where name = DB_NAME()) <> 0 begin EXEC @retcode = dbo.sp_helpmergepublication @publication, @found output IF @@ERROR <> 0 OR @retcode <> 0 BEGIN RETURN (1) END IF @found <> 0 BEGIN RAISERROR (20025, 16, -1, @publication) RETURN (1) END end /* ** Get distribution server information for remote RPC ** agent verification. */ EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distribdb OUTPUT IF @@error <> 0 OR @retcode <> 0 BEGIN RAISERROR (14071, 16, -1) RETURN (1) END /* ** Parameter Check: @sync_method ** The synchronization method must be one of the following: ** ** 0 [bcp] native ** 1 [bcp] character */ SELECT @sync_method = LOWER(@sync_method) IF @sync_method IS NULL OR @sync_method NOT IN ('native', 'character', 'bcp native', 'bcp character') BEGIN RAISERROR (14014, 16, -1) RETURN (1) END IF @sync_method IN ('character', 'bcp character') SELECT @smid = 1 ELSE SELECT @smid = 0 /* ** Parameter Check: @repl_freq. ** Make sure that the replication frequency is one of the following: ** ** id frequency ** == ========== ** 0 continuous ** 1 snapshot */ SELECT @repl_freq = LOWER(@repl_freq) IF @repl_freq IS NULL OR @repl_freq NOT IN ('continuous', 'snapshot') BEGIN RAISERROR (14015, 16, -1) RETURN (1) END IF @repl_freq = 'snapshot' SELECT @rfid = 1 ELSE SELECT @rfid = 0 -- disable tran publishing on REPLICATION_LIMITED sku exec @qv_value_replication = master.dbo.xp_qv @qv_replication if (@rfid = 0) and ( @qv_value_replication != @qv_replication_unlimited ) begin raiserror(21108, 16, -1) return (1) end /* ** Parameter Check: @restricted. */ IF (@restricted IS NULL) OR (LOWER(@restricted) NOT IN ('true', 'false')) BEGIN RAISERROR (14017, 16, -1) RETURN (1) END /* ** Restricted publications are no longer supported */ IF LOWER(@restricted) = 'true' BEGIN RAISERROR (14147, 16, -1) RETURN(1) END /* ** Parameter Check: @status. ** The @status value can be: ** ** statid status ** ====== ======== ** 0 inactive ** 1 active */ IF @status IS NULL OR LOWER(@status) NOT IN ('inactive', 'active') BEGIN RAISERROR (14012, 16, -1) RETURN (1) END IF LOWER(@status) = 'active' SELECT @statid = 1 ELSE SELECT @statid = 0 /* ** Parameter Check: @independent_agent. */ IF @independent_agent IS NULL OR LOWER(@independent_agent) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@independent_agent') RETURN (1) END IF LOWER(@independent_agent) = 'true' SELECT @independent_agent_id = 1 ELSE SELECT @independent_agent_id = 0 /* ** Parameter Check: @immediate_sync. */ IF @immediate_sync IS NULL OR LOWER(@immediate_sync) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@immediate_sync') RETURN (1) END IF LOWER(@immediate_sync) = 'true' SELECT @immediate_sync_id = 1 ELSE SELECT @immediate_sync_id = 0 /* ** Parameter Check: @enabled_for_internet. */ IF @enabled_for_internet IS NULL OR LOWER(@enabled_for_internet) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@enabled_for_internet') RETURN (1) END IF LOWER(@enabled_for_internet) = 'true' SELECT @enabled_for_internet_id = 1 ELSE SELECT @enabled_for_internet_id = 0 /* ** Parameter Check: @allow_push. */ IF @allow_push IS NULL OR LOWER(@allow_push) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@allow_push') RETURN (1) END IF LOWER(@allow_push) = 'true' SELECT @allow_push_id = 1 ELSE SELECT @allow_push_id = 0 /* ** Parameter Check: @allow_pull. */ IF @allow_pull IS NULL OR LOWER(@allow_pull) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@allow_pull') RETURN (1) END IF LOWER(@allow_pull) = 'true' SELECT @allow_pull_id = 1 ELSE SELECT @allow_pull_id = 0 /* ** Parameter Check: @allow_anonymous. */ IF @allow_anonymous IS NULL OR LOWER(@allow_anonymous) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@allow_anonymous') RETURN (1) END IF LOWER(@allow_anonymous) = 'true' SELECT @allow_anonymous_id = 1 ELSE SELECT @allow_anonymous_id = 0 /* Immediate_sync publications have to be independent_agent */ IF @immediate_sync_id = 1 AND @independent_agent_id = 0 BEGIN RAISERROR (21022, 16, -1) RETURN (1) END /* ** Non-immediate sync do not support anonymous subscriptions. */ IF @immediate_sync_id = 0 AND @allow_anonymous_id = 1 BEGIN RAISERROR (20011, 16, -1) RETURN (1) END -- SyncTran /* ** Parameter Check: @allow_sync_tran */ IF @allow_sync_tran IS NULL OR LOWER(@allow_sync_tran) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@allow_sync_tran') RETURN (1) END IF LOWER(@allow_sync_tran) = 'true' BEGIN SELECT @allow_sync_tran_id = 1 --Parameter Check: @autogen_sync_procs IF @autogen_sync_procs IS NULL OR LOWER(@autogen_sync_procs) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@autogen_sync_procs') RETURN (1) END IF LOWER(@autogen_sync_procs) = 'true' SELECT @autogen_sync_procs_id = 1 ELSE SELECT @autogen_sync_procs_id = 0 END ELSE BEGIN SELECT @allow_sync_tran_id = 0 SELECT @autogen_sync_procs_id = 0 END -- end SyncTran /* ** Get distribution server information for remote RPC call. */ EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distribdb OUTPUT IF @@ERROR <> 0 or @retcode <> 0 BEGIN GOTO UNDO END /* ** Add publication to syspublications. */ begin tran save TRAN sp_addpublication select @dbname = db_name() /* ** Construct Log Reader agent name. */ IF @rfid = 0 and NOT EXISTS (SELECT * FROM syspublications where repl_freq = 0) BEGIN /* ** Schedule Log Reader agent for the database */ SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb +'.dbo.sp_MSadd_logreader_agent' EXECUTE @retcode = @distproc @publisher = @@SERVERNAME, @publisher_db = @dbname, @publication = 'ALL', @local_job = 1 IF @@ERROR <> 0 or @retcode <> 0 GOTO UNDO END INSERT syspublications(description, name, repl_freq, status, sync_method, snapshot_jobid, independent_agent, immediate_sync, enabled_for_internet, allow_push, allow_pull, allow_anonymous, immediate_sync_ready, -- SyncTran allow_sync_tran, autogen_sync_procs, retention) VALUES (@description, @publication, @rfid, @statid, @smid, NULL, @independent_agent_id, @immediate_sync_id, @enabled_for_internet_id, @allow_push_id, @allow_pull_id, @allow_anonymous_id, 0, -- SyncTran @allow_sync_tran_id, @autogen_sync_procs_id, @retention) IF @@ERROR <> 0 BEGIN RAISERROR (14018, 16, -1) GOTO UNDO END SELECT @pubid = @@IDENTITY DECLARE @false bit SELECT @false = 0 DECLARE @null sysname SELECT @null = NULL /* ** Add the publication to the distributor side */ SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + '.dbo.sp_MSadd_publication' EXECUTE @retcode = @distproc @publisher = @@SERVERNAME, @publisher_db = @dbname, @publication = @publication, @publication_type = @rfid, @independent_agent = @independent_agent_id, @immediate_sync = @immediate_sync_id, @allow_push = @allow_push_id, @allow_pull = @allow_pull_id, @allow_anonymous = @allow_anonymous_id, @snapshot_agent = @null, @logreader_agent = @agentname, @description = @description, @retention = @retention IF @@ERROR <> 0 or @retcode <> 0 BEGIN GOTO UNDO END -- Populate the initial list. exec @retcode = dbo.sp_grant_publication_access @publication = @publication, @login = null, @reserved = 'init' IF @@error <> 0 OR @retcode <> 0 GOTO UNDO COMMIT TRAN RETURN(0) UNDO: IF @@TRANCOUNT > 0 begin ROLLBACK TRAN sp_addpublication COMMIT TRAN end return 1 go EXEC dbo.sp_MS_marksystemobject sp_addpublication GO print '' print 'Creating procedure sp_changepublication' go CREATE PROCEDURE sp_changepublication ( @publication sysname = NULL, /* Publication name */ @property nvarchar(20) = NULL, /* The property to change */ @value nvarchar(255) = NULL /* The new property value */ ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @cmd nvarchar(255) DECLARE @cmd2 nvarchar(255) DECLARE @pubid int DECLARE @replfreqid tinyint DECLARE @retcode int DECLARE @statusid tinyint DECLARE @syncmethodid tinyint DECLARE @distributor sysname DECLARE @distproc nvarchar (255) DECLARE @subscribed int DECLARE @virtual_id smallint DECLARE @prev_value_bit bit DECLARE @value_bit bit DECLARE @allow_anonymous bit DECLARE @push int DECLARE @pull int DECLARE @independent_agent bit DECLARE @immediate_sync bit DECLARE @distribdb sysname DECLARE @dbname sysname DECLARE @taskid int DECLARE @add_virtual_back bit SELECT @add_virtual_back = 0 SELECT @push = 0 SELECT @pull = 1 SELECT @subscribed = 1 SELECT @virtual_id = -1 /* ** Security Check */ exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Check to see if the database has been activated for publication. */ IF (SELECT category & 1 FROM master..sysdatabases WHERE name = DB_NAME()) = 0 BEGIN RAISERROR (14013, 16, -1) RETURN (1) END /* ** 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 ('description') --INSERT INTO #tab1 VALUES ('taskid') INSERT INTO #tab1 VALUES ('sync_method') INSERT INTO #tab1 VALUES ('status') INSERT INTO #tab1 VALUES ('repl_freq') INSERT INTO #tab1 VALUES ('independent_agent') INSERT INTO #tab1 VALUES ('immediate_sync') INSERT INTO #tab1 VALUES ('enabled_for_internet') INSERT INTO #tab1 VALUES ('allow_push') INSERT INTO #tab1 VALUES ('allow_pull') INSERT INTO #tab1 VALUES ('allow_anonymous') INSERT INTO #tab1 VALUES ('retention') PRINT '' SELECT * FROM #tab1 RETURN (0) END /* ** Parameter Check: @publication. ** Make sure that the publication exists. */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) SELECT @allow_anonymous = allow_anonymous, @pubid = pubid, @immediate_sync = immediate_sync, @independent_agent = independent_agent FROM syspublications WHERE name = @publication IF @pubid IS NULL BEGIN RAISERROR (20026, 11, -1, @publication) RETURN (1) END ELSE /* ** Parameter Check: @property. ** Check to make sure that @property is a valid property in ** syspublications. */ -- Note: must change message 14078 when adding a new property. IF LOWER(@property) NOT IN ( 'taskid','description', 'sync_method', 'status', 'repl_freq','immediate_sync', 'independent_agent', 'enabled_for_internet', 'allow_push', 'allow_pull', 'allow_anonymous', 'retention') BEGIN RAISERROR (14078, 16, -1) RETURN (1) END /* ** Change the property. */ begin tran save TRAN sp_changepublication IF LOWER(@property) ='description' BEGIN UPDATE syspublications SET description = @value WHERE pubid = @pubid IF @@ERROR <> 0 GOTO UNDO END IF LOWER(@property) ='retention' BEGIN if @value is NULL BEGIN RAISERROR(20081, 16, -1, @property) GOTO UNDO END UPDATE syspublications SET retention = convert(int, @value) WHERE pubid = @pubid IF @@ERROR <> 0 GOTO UNDO END IF LOWER(@property) = 'taskid' BEGIN -- No longer supported RAISERROR (21023, 16, -1,'@taskid') RETURN(1) END IF LOWER(@property) = 'sync_method' BEGIN /* ** Check for a valid synchronization method. */ IF LOWER(@value) NOT IN ('native', 'character', 'bcp native', 'bcp character') BEGIN RAISERROR (14014, 16, -1) GOTO UNDO END /* ** Determine the integer value for the sync_method. */ IF LOWER(@value) IN ('native', 'bcp native') SELECT @syncmethodid = 0 ELSE IF LOWER(@value) IN ('character', 'bcp character') SELECT @syncmethodid = 1 /* ** Update the publication with the new synchronization method. */ UPDATE syspublications SET sync_method = @syncmethodid WHERE pubid = @pubid IF @@ERROR <> 0 GOTO UNDO END IF LOWER(@property) = 'status' BEGIN /* ** Check to make sure that we have a valid status. */ IF LOWER(@value) NOT IN ('active', 'inactive') BEGIN RAISERROR (14012, 16, -1) GOTO UNDO END /* ** Determine the integer value for the status. */ IF LOWER(@value) = 'active' SELECT @statusid = 1 ELSE SELECT @statusid = 0 /* If status changed */ IF EXISTS (SELECT * FROM syspublications WHERE pubid = @pubid AND status <> @statusid) BEGIN /* ** If change the status of the publication, ** virtual anonymous subscription have to be recreated. ** */ IF @allow_anonymous = 1 BEGIN /* Drop virtual subscriptions */ EXEC @retcode = dbo.sp_dropsubscription @publication = @publication, @article = 'all', @subscriber = NULL, @reserved = 'internal' IF @@ERROR <> 0 OR @retcode <> 0 BEGIN GOTO UNDO END END /* ** Update the publication with the new status. */ UPDATE syspublications SET status = @statusid WHERE pubid = @pubid IF @@ERROR <> 0 BEGIN GOTO UNDO END IF @allow_anonymous = 1 SELECT @add_virtual_back = 1 END END IF LOWER(@property) = 'repl_freq' BEGIN /* ** Check for a valid replication frequency value. */ IF LOWER(@value) NOT IN ('continuous', 'snapshot') BEGIN RAISERROR (14015, 16, -1) GOTO UNDO END /* ** Determine the integer value for the replication frequency. */ IF LOWER(@value) = 'continuous' SELECT @replfreqid = 0 ELSE SELECT @replfreqid = 1 /* ** Only unsubscribed publications may have this modified. */ IF EXISTS (SELECT * FROM syssubscriptions WHERE status <> @subscribed AND srvid >= 0 AND artid IN (SELECT artid FROM sysarticles where pubid = @pubid)) BEGIN RAISERROR (14033, 11, -1) GOTO UNDO END IF @immediate_sync = 1 BEGIN /* Drop virtual subscriptions */ EXEC @retcode = dbo.sp_dropsubscription @publication = @publication, @article = 'all', @subscriber = NULL, @reserved = 'internal' IF @@ERROR <> 0 OR @retcode <> 0 BEGIN GOTO UNDO END END /* ** Update the publication with the new replication frequency. */ UPDATE syspublications SET repl_freq = @replfreqid WHERE pubid = @pubid IF @@ERROR <> 0 BEGIN GOTO UNDO END IF @immediate_sync = 1 SELECT @add_virtual_back = 1 END IF LOWER(@property) IN ('independent_agent', 'immediate_sync','enabled_for_internet', 'allow_push', 'allow_pull', 'allow_anonymous') BEGIN /* ** Check for a valid value. */ IF LOWER(@value) NOT IN ('true', 'false') BEGIN RAISERROR (14137, 16, -1) GOTO UNDO END /* ** set value bit */ IF LOWER(@value) = 'true' SELECT @value_bit = 1 ELSE SELECT @value_bit = 0 IF LOWER(@property) = 'independent_agent' BEGIN SELECT @prev_value_bit = independent_agent FROM syspublications WHERE name = @publication IF @prev_value_bit <> @value_bit BEGIN IF @immediate_sync = 1 AND @value_bit = 0 BEGIN RAISERROR (21022, 16, -1) GOTO UNDO END /* ** no subscriptions are allowed */ IF EXISTS (SELECT * FROM syssubscriptions ss, sysarticles sa WHERE ss.artid = sa.artid AND sa.pubid = @pubid AND ss.srvid <> @virtual_id ) BEGIN RAISERROR (20013, 16, -1, @property) GOTO UNDO END /* Update the publication type */ UPDATE syspublications SET independent_agent = @value_bit WHERE pubid = @pubid IF @@error <> 0 BEGIN GOTO UNDO END END END IF LOWER(@property) = 'immediate_sync' BEGIN SELECT @prev_value_bit = immediate_sync FROM syspublications WHERE name = @publication IF @prev_value_bit <> @value_bit BEGIN IF @independent_agent = 0 AND @value_bit = 1 BEGIN RAISERROR (21022, 16, -1) GOTO UNDO END /* ** The publication has to be immediate_sync type to ** allow anonymous subscriptions */ IF @value_bit = 0 AND EXISTS (SELECT * FROM syspublications WHERE pubid = @pubid AND allow_anonymous = 1 ) BEGIN RAISERROR (20011, 16, -1, @property) GOTO UNDO END /* ** If turn on immediate_sync, we need to add virtual subscriptions, ** Otherwise, we need to drop them ** When adding, we need to change publication bit first ** When dropping, we need to change publication bit second */ IF @value_bit = 0 BEGIN -- Drop virtual subscriptions EXEC @retcode = dbo.sp_dropsubscription @publication = @publication, @article = 'all', @subscriber = NULL, @reserved = 'internal' IF @@ERROR <> 0 OR @retcode <> 0 BEGIN GOTO UNDO END -- Reset the immediate_sync ready bit UPDATE syspublications SET immediate_sync_ready = 0 WHERE pubid = @pubid END /* Update the publication type */ UPDATE syspublications SET immediate_sync = @value_bit WHERE pubid = @pubid IF @@error <> 0 BEGIN GOTO UNDO END IF @value_bit = 1 SELECT @add_virtual_back = 1 END END IF LOWER(@property) = 'allow_anonymous' BEGIN SELECT @prev_value_bit = allow_anonymous FROM syspublications WHERE name = @publication IF @prev_value_bit <> @value_bit BEGIN /* ** The publication has to be immediate_sync type to ** allow anonymous subscriptions */ IF @value_bit = 1 AND NOT EXISTS (SELECT * FROM syspublications WHERE pubid = @pubid AND immediate_sync = 1 ) BEGIN RAISERROR (20011, 16, -1, @property) GOTO UNDO END /* Drop virtual subscriptions */ EXEC @retcode = dbo.sp_dropsubscription @publication = @publication, @article = 'all', @subscriber = NULL, @reserved = 'internal' IF @@ERROR <> 0 OR @retcode <> 0 BEGIN GOTO UNDO END /* Update the publication type */ UPDATE syspublications SET allow_anonymous = @value_bit WHERE pubid = @pubid IF @@error <> 0 BEGIN GOTO UNDO END /* ** add virtual subscriptions back again to enable ** anonymous subscription. */ SELECT @add_virtual_back = 1 END END IF LOWER(@property) = 'enabled_for_internet' BEGIN /* Update the publication type */ UPDATE syspublications SET enabled_for_internet = @value_bit WHERE pubid = @pubid IF @@error <> 0 BEGIN GOTO UNDO END END IF LOWER(@property) = 'allow_push' BEGIN /* ** If turn it off, make sure there's no push subscriptions left */ IF @value_bit = 0 AND EXISTS (SELECT * FROM syssubscriptions ss, sysarticles sa WHERE ss.artid = sa.artid AND sa.pubid = @pubid AND ss.subscription_type = @push AND ss.srvid <> @virtual_id ) BEGIN RAISERROR (20012, 16, -1) GOTO UNDO END /* Update the publication type */ UPDATE syspublications SET allow_push = @value_bit WHERE pubid = @pubid IF @@error <> 0 BEGIN GOTO UNDO END END IF LOWER(@property) = 'allow_pull' BEGIN /* ** If turn it off, make sure there's no pull subscriptions left */ IF @value_bit = 0 AND EXISTS (SELECT * FROM syssubscriptions ss, sysarticles sa WHERE ss.artid = sa.artid AND sa.pubid = @pubid AND ss.subscription_type = @pull AND ss.srvid <> @virtual_id ) BEGIN RAISERROR (20013, 16, -1, @property) GOTO UNDO END /* Update the publication type */ UPDATE syspublications SET allow_pull = @value_bit WHERE pubid = @pubid IF @@error <> 0 BEGIN GOTO UNDO END END END /* Update publication property at the distributor side if necessary */ IF LOWER(@property) IN ('description', 'repl_freq', 'independent_agent', 'immediate_sync', 'allow_push', 'allow_pull', 'allow_anonymous','retention') BEGIN /* Translate the property names and values */ IF LOWER(@property) = 'repl_freq' BEGIN SELECT @property = 'publication_type' SELECT @value = STR(@replfreqid) END /* Translate values */ IF LOWER(@value) = 'true' SELECT @value = '1' ELSE IF LOWER(@value) = 'false' SELECT @value = '0' /* ** Get distribution server information for remote RPC call. */ EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distribdb OUTPUT IF @@ERROR <> 0 or @retcode <> 0 BEGIN GOTO UNDO END SELECT @dbname = DB_NAME() SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + '.dbo.sp_MSchange_publication' EXECUTE @retcode = @distproc @publisher = @@SERVERNAME, @publisher_db = @dbname, @publication = @publication, @property = @property, @value = @value IF @@ERROR <> 0 OR @retcode <> 0 BEGIN GOTO UNDO END END IF @add_virtual_back = 1 BEGIN /* Add virtual subscriptions back*/ EXEC @retcode = dbo.sp_addsubscription @publication = @publication, @article = 'all', @subscriber = NULL, @destination_db = 'virtual', @sync_type = 'automatic', @status = NULL, @reserved = 'internal' IF @@ERROR <> 0 OR @retcode <> 0 BEGIN GOTO UNDO END END COMMIT TRAN /* ** Return succeed. */ RAISERROR (14077, 10, -1) RETURN (0) UNDO: IF @@TRANCOUNT > 0 begin ROLLBACK TRAN sp_changepublication COMMIT TRAN end GO EXEC dbo.sp_MS_marksystemobject sp_changepublication GO print '' print 'Creating procedure sp_changesubscription' GO /* This function should be disallowed */ CREATE PROCEDURE sp_changesubscription ( @publication sysname = NULL, /* Publication name */ @article sysname = NULL, /* Article name */ @subscriber sysname, /* Subscriber name */ @property nvarchar(15) = NULL, /* The property to change */ @value nvarchar(255) = NULL /* The new property value */ ) AS SET NOCOUNT ON RAISERROR (21023, 16, -1,'sp_changesubscription') RETURN(1) go dump tran master with no_log go EXEC dbo.sp_MS_marksystemobject sp_changesubscription GO print '' print 'Creating procedure sp_helparticle' go CREATE PROCEDURE sp_helparticle ( @publication sysname, /* The publication name */ @article sysname = '%', /* The article name */ @returnfilter bit = 1 /* Return filter flag */ ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @pubid int DECLARE @retcode int DECLARE @subscriber_bit smallint DECLARE @publish_bit int DECLARE @source_object sysname DECLARE @source_owner sysname SELECT @publish_bit = 1 /* ** Security Check. To public. */ /* ** Check if the database is published. */ IF NOT EXISTS (SELECT * FROM master..sysdatabases WHERE name = db_name() AND (category & @publish_bit) = @publish_bit) RETURN(0) /* ** Initializations. */ SELECT @subscriber_bit = 4 IF @publication IS NOT NULL SELECT @pubid = pubid FROM syspublications WHERE name = @publication /* ** Create a temporary table to hold all information. */ CREATE TABLE #tab1 ( artid int NOT NULL, columns varbinary(32) NOT NULL, creation_script nvarchar(255) NULL, del_cmd nvarchar(255) NULL, description nvarchar(255) NULL, dest_table sysname NULL, old_filter int NULL, ins_cmd nvarchar(255) NULL, name sysname NOT NULL, objid int NOT NULL, pubid int NOT NULL, status tinyint NOT NULL, sync_objid int NOT NULL, type tinyint NOT NULL, upd_cmd nvarchar(255) NULL, source_table nvarchar(257) NULL, /* converted from objid */ filter nvarchar(257) NULL, /* converted from old_filter */ sync_object nvarchar(257) NULL, /* converted from sync_objid */ vpartition bit NOT NULL, /* computed */ pre_creation_cmd tinyint NOT NULL, filter_clause ntext NULL, schema_option binary(8) NULL, dest_owner sysname NULL, source_owner sysname NULL, /* these two columns are for 7.0 use only */ unqua_source_object sysname NULL, /* column source_table stays due to backward compatibility */ sync_object_owner sysname NULL, unqua_sync_object sysname NULL, filter_owner sysname NULL, unqua_filter sysname NULL ) CREATE UNIQUE INDEX idx1 ON #tab1 (name, pubid) /* ** Parameter Check: @publication. ** Check to make sure that there are some articles ** to display. */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @retcode <> 0 RETURN (1) IF NOT EXISTS (SELECT * FROM syspublications WHERE name = @publication) BEGIN RAISERROR (20026, 11, -1, @publication) RETURN (1) END /* ** Parameter Check: @article. ** Check to make sure that the article exists, that it conforms ** to the rules for identifiers, and that it isn't NULL. */ IF @article IS NULL BEGIN RAISERROR (14043, 16, -1, '@article') RETURN (1) END IF @article <> '%' BEGIN /* EXECUTE @retcode = dbo.sp_validname @article IF @retcode <> 0 RETURN (1) */ IF NOT EXISTS (SELECT * FROM sysarticles WHERE name = @article AND pubid IN (SELECT pubid FROM syspublications WHERE name = @publication)) BEGIN RAISERROR (20027, 11, -1, @article) RETURN (1) END END IF @returnfilter = 1 BEGIN INSERT INTO #tab1 (artid, columns, creation_script, del_cmd, description, dest_table, old_filter, ins_cmd, name, objid, pubid, status, sync_objid, type, upd_cmd, source_table, filter, vpartition, pre_creation_cmd, filter_clause, schema_option, dest_owner, source_owner, unqua_source_object, sync_object_owner, unqua_sync_object, filter_owner, unqua_filter) (SELECT artid, columns, creation_script, del_cmd, a.description, dest_table, filter, ins_cmd, a.name, objid, a.pubid, a.status, sync_objid, a.type, upd_cmd, NULL, NULL, 0, a.pre_creation_cmd, a.filter_clause, a.schema_option, a.dest_owner, user_name(o.uid), o.name, user_name(sync.uid), sync.name, user_name(fltr.uid), fltr.name FROM syspublications b, sysobjects o, sysobjects sync, sysarticles a LEFT JOIN sysobjects fltr on a.filter = fltr.id WHERE a.name LIKE @article AND a.objid = o.id AND a.sync_objid = sync.id AND a.pubid = b.pubid AND b.name = @publication) END ELSE BEGIN INSERT INTO #tab1 (artid, columns, creation_script, del_cmd, description, dest_table, old_filter, ins_cmd, name, objid, pubid, status, sync_objid, type, upd_cmd, source_table, filter, vpartition, pre_creation_cmd, filter_clause, schema_option, dest_owner, source_owner, unqua_source_object, sync_object_owner, unqua_sync_object, filter_owner, unqua_filter) (SELECT artid, columns, creation_script, del_cmd, a.description, dest_table, filter, ins_cmd, a.name, objid, a.pubid, a.status, sync_objid, a.type, upd_cmd, NULL, NULL, 0, a.pre_creation_cmd, NULL, schema_option, dest_owner, user_name(o.uid), o.name, user_name(sync.uid), sync.name, user_name(fltr.uid), fltr.name FROM syspublications b, sysobjects o, sysobjects sync, sysarticles a LEFT JOIN sysobjects fltr on a.filter = fltr.id WHERE a.name LIKE @article AND a.objid = o.id AND a.sync_objid = sync.id AND a.pubid = b.pubid AND b.name = @publication) END UPDATE #tab1 SET source_table = QUOTENAME(u.name) + '.' + QUOTENAME(o.name) FROM #tab1, sysobjects o, sysusers u WHERE o.id = #tab1.objid AND o.uid = u.uid UPDATE #tab1 SET unqua_sync_object = sysobjects.name from sysobjects where sysobjects.id = sync_objid UPDATE #tab1 SET sync_object = QUOTENAME(sysusers.name) + '.' + QUOTENAME(sysobjects.name) FROM sysobjects, sysusers WHERE sysobjects.id = sync_objid AND sysobjects.uid = sysusers.uid UPDATE #tab1 SET filter = (SELECT sysusers.name + '.' + sysobjects.name FROM sysobjects, sysusers WHERE sysobjects.id = #tab1.old_filter AND sysobjects.uid = sysusers.uid) FROM #tab1 DECLARE hC CURSOR LOCAL FAST_FORWARD FOR SELECT name, pubid FROM #tab1 OPEN hC FETCH hC INTO @article, @pubid WHILE (@@fetch_status <> -1) BEGIN IF EXISTS (SELECT * FROM sysarticles a, syscolumns b WHERE ( convert(bit, convert( varbinary, substring( convert( nvarchar, a.columns ), 16 - floor((colid-1)/16),1 )) & power( 2, ((colid-1)%16))) = 0 OR convert(bit, convert( varbinary, substring( convert( nvarchar, a.columns ), 16 - floor((colid-1)/16),1 )) & power( 2, ((colid-1)%16))) IS NULL ) AND a.objid = b.id AND a.name = @article AND a.pubid = @pubid) UPDATE #tab1 SET vpartition = 1 WHERE name = @article AND pubid = @pubid FETCH hC INTO @article, @pubid END CLOSE hC DEALLOCATE hC IF @returnfilter = 1 SELECT 'article id' = artid, 'article name' = name, 'base object' = source_table, 'destination object' = dest_table, 'synchronization object' = sync_object, 'type' = type, 'status' = status, 'filter' = filter, 'description' = description, 'insert_command' = ins_cmd, 'update_command' = upd_cmd, 'delete_command' = del_cmd, 'creation script path' = creation_script, 'vertical partition' = vpartition, 'pre_creation_cmd' = pre_creation_cmd, 'filter_clause' = filter_clause, 'schema_option' = schema_option, 'dest_owner' = dest_owner, 'source_owner' = source_owner, 'unqua_source_object' = unqua_source_object, 'sync_object_owner' = sync_object_owner, 'unqualified_sync_object' = unqua_sync_object, 'filter_owner' = filter_owner, 'unqua_filter' = unqua_filter FROM #tab1 ORDER BY 2 ELSE SELECT 'article id' = artid, 'article name' = name, 'base object' = source_table, 'destination object' = dest_table, 'synchronization object' = sync_object, 'type' = type, 'status' = status, 'filter' = filter, 'description' = description, 'insert_command' = ins_cmd, 'update_command' = upd_cmd, 'delete_command' = del_cmd, 'creation script path' = creation_script, 'vertical partition' = vpartition, 'pre_creation_cmd' = pre_creation_cmd, 'filter_clause' = NULL, 'schema_option' = schema_option, 'dest_owner' = dest_owner, 'source_owner' = source_owner, 'unqualified_source_object' = unqua_source_object, 'sync_object_owner' = sync_object_owner, 'unqualified_sync_object' = unqua_sync_object, 'filter_owner' = filter_owner, 'unqualified_filter' = unqua_filter FROM #tab1 ORDER BY 2 RETURN (0) go dump tran master with no_log go EXEC dbo.sp_MS_marksystemobject sp_helparticle GO print '' print 'Creating procedure sp_articlecolumn' go CREATE PROCEDURE sp_articlecolumn ( @publication sysname, /* The publication name */ @article sysname, /* The article name */ @column sysname = NULL, /* The column name */ @operation nvarchar(4) = 'add' /* Add or delete a column */ -- synctran , @refresh_synctran_procs bit = 1 -- refresh synctran procs or not , @ignore_distributor bit = 0 ) AS /* ** Declarations. */ DECLARE @bit tinyint /* Bit offset */ --DECLARE @byte tinyint /* Byte offset */ DECLARE @word tinyint /* word offset */ DECLARE @cnt tinyint, @idx tinyint /* Loop counter, index */ DECLARE @columns binary(32) /* Temporary storage for the converted column */ DECLARE @mask binary(2) /* Bit mask to set the bit on */ DECLARE @mval int -- DECLARE @newbyte binary(1) /* New byte to replace old byte with */ -- DECLARE @oldbyte binary(1) /* Temporary storage for original byte */ DECLARE @newword binary(2) DECLARE @oldword binary(2) DECLARE @pubid int /* Publication identification number */ DECLARE @retcode int /* Return code for stored procedures */ -- DECLARE @zero binary(32) /* Constant: 0 */ DECLARE @artid int DECLARE @inactive tinyint DECLARE @objid int /* Article base table id */ DECLARE @tablename sysname select @inactive = 0 /* ** Security Check */ exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Check to see if the database has been activated for publication. ** Do not check if @ignore_distributor indicates brute force cleanup. */ IF ( (SELECT category & 1 FROM master..sysdatabases WHERE name = DB_NAME()) = 0 ) and ( @ignore_distributor = 0 ) BEGIN RAISERROR (14013, 16, -1) RETURN (1) END /* ** Parameter Check: @publication. ** Make sure that the publication exists and that it conforms to the ** rules for identifiers. */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @retcode <> 0 RETURN (1) SELECT @pubid = pubid FROM syspublications WHERE name = @publication IF @pubid IS NULL BEGIN RAISERROR (20026, 11, -1, @publication) RETURN (1) END ELSE /* ** Parameter Check: @article. ** Check to make sure that the article exists in the publication. */ IF @article IS NULL BEGIN RAISERROR (14043, 16, -1, '@article') RETURN (1) END /* EXECUTE @retcode = dbo.sp_validname @article IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) */ /* ** Make sure the article exists. */ SELECT @artid = artid FROM sysarticles WHERE pubid = @pubid AND name = @article IF @artid IS NULL BEGIN RAISERROR (20027, 11, -1, @article) RETURN (1) END /* ** Only unsubscribed articles may be modified. (excluding virtual subscriptions) */ IF EXISTS (SELECT * FROM syssubscriptions WHERE artid = @artid AND status <> @inactive AND srvid >= 0) BEGIN RAISERROR (14092, 11, -1) RETURN (1) END /* ** Error out if this is a not a table based article */ IF NOT EXISTS ( SELECT * FROM sysarticles WHERE artid = @artid AND pubid = @pubid AND (type & 1) = 1 ) BEGIN RAISERROR (14112, 11, -1 ) RETURN (1) END /* ** Parameter Check: @column. ** Check to make sure that the column exists and conforms to the rules ** for identifiers. */ /* IF @column IS NOT NULL BEGIN EXECUTE @retcode = dbo.sp_validname @column IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) END */ /* ** Parameter Check: @operation. ** The operation can be either 'add' or 'drop'. */ IF LOWER(@operation) NOT IN ('add', 'drop') BEGIN RAISERROR (14019, 16, -1) RETURN (1) END SELECT @objid = (SELECT objid FROM sysarticles WHERE artid = @artid) SELECT @tablename = OBJECT_NAME(@objid) begin tran save TRANSACTION articlecolumn /* ** Make sure that the columns column is not NULL. */ -- SELECT @zero = 0x00 SELECT @columns = columns FROM sysarticles WHERE artid = @artid IF @columns IS NULL UPDATE sysarticles SET columns = 0x00 WHERE artid = @artid /* ** If no columns are specified, or if NULL is specified, set all ** the bits in the 'columns' column so all columns will be included. */ IF @column IS NULL BEGIN /* ** Fetch the number of columns affected. */ SELECT @cnt = COUNT(*), @idx = 1 FROM syscolumns WHERE id = @objid SELECT @columns = 0x00 WHILE @idx <= @cnt BEGIN SELECT @word = CONVERT(tinyint, 16 - FLOOR((@idx-1)/16)) SELECT @bit = (@idx-1) % 16 IF LOWER(@operation) = 'add' SELECT @mval = POWER(2, @bit) ELSE SELECT @mval = ~POWER(2, @bit) SELECT @mask = convert( binary(2), substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) ) SELECT @oldword = CONVERT( binary(2), SUBSTRING( CONVERT( nvarchar,@columns), @word, 1) ) IF @oldword IS NULL SELECT @oldword = 0x0000 IF LOWER(@operation) = 'add' SELECT @newword = CONVERT(binary(2), convert(smallint, @oldword) | @mask) ELSE SELECT @newword = CONVERT(binary(2), convert(smallint, @oldword ) & @mask) SELECT @columns = CONVERT(binary(32), STUFF( convert(nchar(16),@columns), @word, 1, convert( nchar(1), @newword))) SELECT @idx = @idx + 1 END IF LOWER(@operation) = 'drop' BEGIN /* Update Text\Image column status as not published */ EXECUTE @retcode = dbo.sp_MSarticletextcol @artid, NULL, 'publish', @operation IF (@@error <> 0 OR @retcode <> 0) BEGIN if @@trancount > 0 begin ROLLBACK TRANSACTION articlecolumn commit tran end RAISERROR (14020, 16, -1) RETURN (1) END END UPDATE sysarticles SET columns = @columns WHERE name = @article AND pubid = @pubid IF LOWER(@operation) = 'add' BEGIN /* Update Text\Image column status as published */ EXECUTE @retcode = dbo.sp_MSarticletextcol @artid, NULL, 'publish', @operation IF (@@error <> 0 OR @retcode <> 0) BEGIN if @@trancount > 0 begin ROLLBACK TRANSACTION articlecolumn commit tran end RAISERROR (14020, 16, -1) RETURN (1) END END END ELSE BEGIN IF EXISTS (SELECT * FROM sysarticles WHERE name = @article AND pubid = @pubid AND columns IS NULL) UPDATE sysarticles SET columns = 0x00 WHERE name = @article AND pubid = @pubid DECLARE @columnid smallint /* Columnid-1 = bit to set */ /* ** Get the column id for this column. We'll use the column id ** to determine the bit in the 'columns' column. The bit we want ** is equal to the columnid - 1. */ SELECT @columnid = colid FROM syscolumns WHERE id = @objid AND name = @column IF ((@@error <> 0) OR (@columnid IS NULL)) BEGIN if @@trancount > 0 begin ROLLBACK TRANSACTION articlecolumn commit tran end RAISERROR (14020, 16, -1) RETURN (1) END -- If the publication is allow_sync_tran, we cannot drop the timestamp -- column from the partition. if exists (select * from syspublications where name = @publication and allow_sync_tran = 1) and LOWER(@operation) = 'drop' begin declare @ts_col sysname exec dbo.sp_MSis_col_replicated @publication, @article, 'timestamp', @ts_col OUTPUT if @ts_col = @column BEGIN if @@trancount > 0 begin ROLLBACK TRANSACTION articlecolumn commit tran end RAISERROR (21080, 16, -1) RETURN (1) END end /* ** Obtain the byte offset and the bit offset, then set the ** mask column for the bit we want to turn on. */ SELECT @word = CONVERT(tinyint, 16 - FLOOR((@columnid-1)/16)) SELECT @bit = (@columnid-1) % 16 IF LOWER(@operation) = 'add' SELECT @mval = POWER(2, @bit) ELSE SELECT @mval = ~POWER(2, @bit) select @mask = convert( binary(2), substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) ) /* ** Save the columns column in a temporary local variable so we ** can twiddle the bit and then put it back into the table. */ SELECT @columns = columns FROM sysarticles WHERE name = @article AND pubid = @pubid /* ** Fish out the byte we're interested in and save it in a ** a temporary local variable. If it's NULL, just set it ** to 0. Then apply the bitwise operator OR to twiddle the ** bit in the old byte and save it in another temporary ** local variable @newbyte. */ SELECT @oldword = CONVERT( binary(2), SUBSTRING( CONVERT( nvarchar,@columns), @word, 1) ) IF @oldword IS NULL SELECT @oldword = 0x0000 IF LOWER(@operation) = 'add' SELECT @newword = CONVERT(binary(2), convert(smallint, @oldword) | @mask) ELSE SELECT @newword = CONVERT(binary(2), convert(smallint, @oldword ) & @mask) SELECT @columns = CONVERT(binary(32), STUFF( convert(nchar(16),@columns), @word, 1, convert( nchar(1), @newword))) SELECT @idx = @idx + 1 IF LOWER(@operation) = 'drop' BEGIN /* Update Text\Image column status as not published */ EXECUTE @retcode = dbo.sp_MSarticletextcol @artid, @columnid, 'publish', @operation IF (@@error <> 0 OR @retcode <> 0) BEGIN if @@trancount > 0 begin ROLLBACK TRANSACTION articlecolumn commit tran end RAISERROR (14021, 16, -1) RETURN (1) END END /* ** Update the sysarticles table. Set the bit to 1 for the ** selected column. */ UPDATE sysarticles SET columns = @columns WHERE name = @article AND pubid = @pubid IF @@error <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRANSACTION articlecolumn commit tran end RAISERROR (14021, 16, -1) RETURN (1) END IF LOWER(@operation) = 'add' BEGIN /* Update Text\Image column status as not published */ EXECUTE @retcode = dbo.sp_MSarticletextcol @artid, @columnid, 'publish', @operation IF (@@error <> 0 OR @retcode <> 0) BEGIN if @@trancount > 0 begin ROLLBACK TRANSACTION articlecolumn commit tran end RAISERROR (14021, 16, -1) RETURN (1) END END END -- Synctran /* ** If publication is enabled for Synctran and sprocs are auto-generated - regenerate them */ declare @autogen_sync_procs_id bit declare @ins_proc_id int, @upd_proc_id int, @del_proc_id int declare @ins_proc sysname, @upd_proc sysname, @del_proc sysname, @owner sysname, @objname sysname declare @sync_pubid int declare @cmd nvarchar(4000) select @autogen_sync_procs_id = autogen_sync_procs, @sync_pubid = pubid from syspublications where name = @publication if @autogen_sync_procs_id = 1 and @refresh_synctran_procs = 1 begin -- Drop existing synctran procs select @owner = user_name(OBJECTPROPERTY(objid, 'OwnerId')) from sysarticles a, syspublications p where a.name = @article and p.name = @publication and a.pubid = p.pubid select @ins_proc_id = sync_ins_proc, @upd_proc_id = sync_upd_proc, @del_proc_id = sync_del_proc from sysarticleupdates where pubid = @pubid and artid = @artid if @ins_proc_id is not null begin select @objname = object_name(@ins_proc_id) exec @retcode = dbo.sp_MSdrop_object @object_name = @objname, @object_owner = @owner if @@error <> 0 or @retcode <> 0 return (1) end if @upd_proc_id is not null begin select @objname = object_name(@upd_proc_id) exec @retcode = dbo.sp_MSdrop_object @object_name = @objname, @object_owner = @owner if @@error <> 0 or @retcode <> 0 return (1) end if @del_proc_id is not null begin select @objname = object_name(@del_proc_id) exec @retcode = dbo.sp_MSdrop_object @object_name = @objname, @object_owner = @owner if @@error <> 0 or @retcode <> 0 return (1) end -- Now generate new ones select @ins_proc = 'sp_MSsync_ins_' + SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @sync_pubid)) select @upd_proc = 'sp_MSsync_upd_' + SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @sync_pubid)) select @del_proc = 'sp_MSsync_del_' + SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @sync_pubid)) -- check uniqueness of names and revert to ugly guid-based name if friendly name already exists if exists (select name from sysobjects where name in (@ins_proc, @upd_proc, @del_proc)) begin declare @guid_name nvarchar(36) select @guid_name = convert (nvarchar(36), newid()) -- remove '-' from guid name because rpc can't handle '-' select @guid_name = replace (@guid_name,'-','_') select @ins_proc = 'sp_MSsync_ins_' + @guid_name select @upd_proc = 'sp_MSsync_upd_' + @guid_name select @del_proc = 'sp_MSsync_del_' + @guid_name end if @ins_proc IS NULL begin if @@trancount > 0 ROLLBACK TRANSACTION RAISERROR (14043, 11, -1, '@ins_proc') RETURN (1) end if @upd_proc IS NULL begin if @@trancount > 0 ROLLBACK TRANSACTION RAISERROR (14043, 11, -1, '@upd_proc') RETURN (1) end if @del_proc IS NULL begin if @@trancount > 0 ROLLBACK TRANSACTION RAISERROR (14043, 11, -1, '@del_proc') RETURN (1) end exec @retcode = dbo.sp_MSgen_sync_tran_procs @publication, @article, @ins_proc, @upd_proc, @del_proc IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN articlecolumn commit tran end RETURN (1) END --retrieve sproc id's, fail if they don't exist SELECT @ins_proc_id = id FROM sysobjects WHERE name = @ins_proc SELECT @upd_proc_id = id FROM sysobjects WHERE name = @upd_proc SELECT @del_proc_id = id FROM sysobjects WHERE name = @del_proc IF (@ins_proc_id IS NULL) OR (@upd_proc_id IS NULL) OR (@del_proc_id IS NULL) BEGIN if @ins_proc_id IS NULL RAISERROR (20500, 16, 1, @ins_proc) if @upd_proc_id IS NULL RAISERROR (20500, 16, 1, @upd_proc) if @del_proc_id IS NULL RAISERROR (20500, 16, 1, @del_proc) if @@trancount > 0 begin ROLLBACK tran articlecolumn commit tran end RETURN (1) END -- perform update in sysarticleupdates update sysarticleupdates set sync_ins_proc = @ins_proc_id, sync_upd_proc = @upd_proc_id, sync_del_proc = @del_proc_id where pubid = @pubid and artid = @artid IF @@ERROR <> 0 BEGIN RAISERROR (20501, 16, -1) if @@trancount > 0 begin ROLLBACK tran articlecolumn commit tran end RETURN (1) END end -- end synctran /* ** Force the article cache to be refreshed with the new definition. ** Nothing to flush if brute force cleanup. */ if ( @ignore_distributor = 0 ) EXECUTE dbo.sp_replflush COMMIT TRANSACTION go EXEC dbo.sp_MS_marksystemobject sp_articlecolumn GO print '' print 'Creating procedure sp_helparticlecolumns' go CREATE PROCEDURE sp_helparticlecolumns ( @publication sysname, /* The publication name */ @article sysname /* The article name */ ) AS /* ** Declarations. */ DECLARE @columns binary(32) DECLARE @pubid int DECLARE @retcode int /* ** Security Check. To public. */ /* ** Parameter Check: @article. ** The @article name must conform to the rules for identifiers. */ IF @article IS NULL BEGIN RAISERROR (14043, 16, -1, '@article') RETURN (1) END /* EXECUTE @retcode = dbo.sp_validname @article IF @retcode <> 0 RETURN (1) */ /* ** Parameter Check: @publication. ** The @publication name must conform to the rules for identifiers. */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @retcode <> 0 RETURN (1) /* ** Get the pubid. */ SELECT @pubid = pubid FROM syspublications WHERE name = @publication IF @pubid IS NULL BEGIN RAISERROR (14043, 11, -1, '@pubid') RETURN (1) END /* ** Parameter Check: @article, @publication. ** Check to make sure that the article exists in this publication. */ IF NOT EXISTS (SELECT * FROM sysarticles WHERE pubid = @pubid AND name = @article) BEGIN RAISERROR (20027, 11, -1, @article) RETURN (1) END /* ** Error out if this is a not a table based article */ IF NOT EXISTS ( SELECT * FROM sysarticles WHERE name = @article AND pubid = @pubid AND (type & 1) = 1 ) BEGIN RAISERROR (14112, 11, -1 ) RETURN (1) END SELECT @columns = columns FROM sysarticles WHERE name = @article AND pubid = @pubid SELECT 'column id' = colid, 'column' = name, 'published' = convert(bit, convert( varbinary, substring( convert( nvarchar, @columns ), 16 - floor((colid-1)/16),1 )) & power( 2, ((colid-1)%16))) FROM syscolumns WHERE id = (SELECT objid FROM sysarticles WHERE name = @article AND pubid = @pubid) go EXEC dbo.sp_MS_marksystemobject sp_helparticlecolumns GO print '' print 'Creating procedure sp_helppublication' go CREATE PROCEDURE sp_helppublication ( @publication sysname = '%', /* The publication name */ @found int = 23456 OUTPUT /* a flag indicate returning row */ ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @pubid int DECLARE @has_subscription bit DECLARE @retcode int DECLARE @no_row bit DECLARE @publish_bit int SELECT @publish_bit = 1 /* ** Check if the database is published. */ IF NOT EXISTS (SELECT * FROM master..sysdatabases WHERE name = db_name() AND (category & @publish_bit) = @publish_bit) RETURN(0) /* ** Security Check. To public. */ /* ** Initializations. */ IF @found = 23456 BEGIN SELECT @no_row=0 END ELSE BEGIN SELECT @no_row=1 END /* ** Parameter Check: @publication. ** Check to make sure that there are some publications ** to display. */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END IF @publication <> '%' BEGIN EXECUTE @retcode = dbo.sp_validname @publication IF @retcode <> 0 RETURN (1) END IF NOT EXISTS (SELECT * FROM syspublications WHERE name like @publication) BEGIN SELECT @found = 0 RETURN (0) END ELSE BEGIN SELECT @found = 1 IF @no_row <>0 RETURN(0) END SELECT 'pubid' = pubid, 'name' = name, 'restricted' = 0, 'status' = status, -- using 'task' is for backward compatible 'task' = convert(int, 1), 'replication frequency' = repl_freq, 'synchronization method' = sync_method, 'description' = description, 'immediate_sync' = immediate_sync, 'enabled_for_internet' = enabled_for_internet, 'allow_push' = allow_push, 'allow_pull' = allow_pull, 'allow_anonymous' = allow_anonymous, 'independent_agent' = independent_agent, 'immediate_sync_ready' = immediate_sync_ready, -- SyncTran 'allow_sync_tran' = allow_sync_tran, 'autogen_sync_procs' = autogen_sync_procs, 'snapshot_jobid' = snapshot_jobid, 'retention' = retention, 'has subscription' = case when EXISTS (select * from syssubscriptions where artid in (select artid from sysarticles where pubid in (select inside.pubid from syspublications inside where inside.name = outter.name))) then 1 else 0 end FROM syspublications outter WHERE name LIKE @publication ORDER BY name RETURN (0) go EXEC dbo.sp_MS_marksystemobject sp_helppublication GO -- bug 44359 : sp_helppublication_snapshot not used anymore print '' print 'Creating procedure sp_helpsubscription' go CREATE PROCEDURE sp_helpsubscription @publication sysname = '%', /* The publication name */ @article sysname = '%', /* The article name */ @subscriber sysname = N'%', /* The subscriber name */ @destination_db sysname = '%', @found int = 23456 OUTPUT AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @retcode int DECLARE @subscriber_bit smallint DECLARE @no_row bit DECLARE @srvid smallint DECLARE @pubid int DECLARE @artid int DECLARE @immediate_sync bit DECLARE @subscription_type_id int DECLARE @sync_typeid int DECLARE @publish_bit int DECLARE @full_subscription bit SELECT @publish_bit = 1 /* Security check. To public. */ /* ** Check if the database is published. */ IF NOT EXISTS (SELECT * FROM master..sysdatabases WHERE name = db_name() AND (category & @publish_bit) = @publish_bit) RETURN(0) /* ** Initializations of @now_row. */ IF @found = 23456 BEGIN SELECT @no_row=0 END ELSE BEGIN SELECT @no_row=1 END /* ** Initializations. */ SELECT @subscriber_bit = 4 /* ** Parameter Check: @subscriber. */ IF @subscriber IS NULL BEGIN RAISERROR (14043, 16, -1, '@subscriber') RETURN (1) END /* ** Parameter Check: @subscriber. ** Check if remote server is defined as a subscription server, and ** that the name conforms to the rules for identifiers. */ IF @subscriber <> '%' BEGIN EXECUTE @retcode = dbo.sp_validname @subscriber select @subscriber = UPPER(@subscriber) IF @retcode <> 0 RETURN (1) IF NOT EXISTS (SELECT * FROM master..sysservers WHERE UPPER(srvname) = UPPER(@subscriber) AND (srvstatus & @subscriber_bit) <> 0) BEGIN RAISERROR (14010, 16, -1) RETURN (1) END END /* ** Parameter Check: @publication. ** If the publication name is specified, check to make sure that it ** conforms to the rules for identifiers and that the publication ** actually exists. Disallow NULL. */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END IF @publication <> '%' BEGIN EXECUTE @retcode = dbo.sp_validname @publication IF @retcode <> 0 RETURN (1) IF NOT EXISTS (SELECT * FROM syspublications WHERE name = @publication) BEGIN RAISERROR (20026, 11, -1, @publication) RETURN (1) END END /* ** Parameter Check: @article. ** If the article name is specified, check to make sure that it ** conforms to the rules for identifiers and that the article ** actually exists. Disallow NULL. ** ** If @article is 'all', only return one entry for the whole publication ** for full subscriptions (subscriptions inlcluding all the articles in a ** publication). ** */ IF @article IS NULL BEGIN RAISERROR (14043, 16, -1, '@article') RETURN (1) END IF LOWER(@article) <> 'all' BEGIN IF @article <> '%' BEGIN /* EXECUTE @retcode = dbo.sp_validname @article IF @retcode <> 0 RETURN (1) */ IF NOT EXISTS (SELECT * FROM sysarticles WHERE name = @article AND pubid IN (SELECT pubid FROM syspublications WHERE name LIKE @publication)) BEGIN RAISERROR (20027, 11, -1, @article) RETURN (1) END END IF EXISTS (SELECT * FROM syssubscriptions sub, master..sysservers ss, syspublications pub, sysarticles art WHERE ((@subscriber = N'%') OR (ss.srvname = @subscriber)) AND sub.srvid = ss.srvid AND pub.name LIKE @publication AND art.name LIKE @article AND art.pubid = pub.pubid AND sub.artid = art.artid AND sub.dest_db LIKE @destination_db AND (sub.login_name = suser_sname(suser_sid()) OR is_srvrolemember('sysadmin') = 1 OR is_member ('db_owner') = 1) ) BEGIN SELECT @found = 1 IF @no_row <> 0 RETURN (0) END ELSE BEGIN SELECT @found = 0 RETURN(0) END END /* SELECT 'subscriber' = ss.srvname, 'publication' = pub.name, 'article' = art.name, 'destination database' = sub.dest_db, 'subscription status' = sub.status, 'synchronization type' = sub.sync_type FROM syssubscriptions sub, master..sysservers ss, syspublications pub, sysarticles art WHERE UPPER(ss.srvname) LIKE UPPER(@subscriber) AND sub.srvid = ss.srvid AND pub.name LIKE @publication AND art.name LIKE @article AND art.pubid = pub.pubid AND sub.artid = art.artid AND (sub.login_name = suser_sname(suser_sid()) OR is_srvrolemember('sysadmin') = 1 OR is_member ('db_owner') = 1) ) ORDER BY subscriber, publication, article */ CREATE TABLE #helpsubscription ( /* Info that will be returned */ subscriber sysname NOT NULL, publication sysname NOT NULL, article sysname NOT NULL, destination_db sysname NOT NULL, status tinyint NOT NULL, sync_type tinyint NOT NULL, subscription_type int NOT NULL, full_subscription bit NOT NULL, /* full subscription or not */ distribution_jobid binary(16) NULL, subscription_name nvarchar(255) NOT NULL, -- SyncTran update_mode int NOT NULL, loopback_detection bit not null ) /* Open a CURSOR LOCAL FOR subscriber/destination_db and publication pair ** ** Get subscriptions ** sa or dbo can see every subscriptions while ** others only see their own. */ /* ** Performance Optimization: Eliminate the 'LIKE' clause for publication name. ** Empirical evidence shows almost 50% speed improvement when ** opening the cursor if publication name is provided. */ IF (@publication <> '%') DECLARE hChelpsubscription_pub CURSOR LOCAL FAST_FORWARD FOR SELECT DISTINCT ss.srvname, pub.name, sub.dest_db, pub.pubid, sub.srvid, pub.immediate_sync FROM syssubscriptions sub, master..sysservers ss, syspublications pub, sysarticles art WHERE ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber))) AND sub.srvid = ss.srvid AND pub.name = @publication AND art.pubid = pub.pubid AND sub.artid = art.artid AND sub.dest_db LIKE @destination_db AND (sub.login_name = suser_sname(suser_sid()) OR is_srvrolemember('sysadmin') = 1 OR is_member ('db_owner') = 1) FOR READ ONLY ELSE DECLARE hChelpsubscription_pub CURSOR LOCAL FAST_FORWARD FOR SELECT DISTINCT ss.srvname, pub.name, sub.dest_db, pub.pubid, sub.srvid, pub.immediate_sync FROM syssubscriptions sub, master..sysservers ss, syspublications pub, sysarticles art WHERE ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber))) AND sub.srvid = ss.srvid AND art.pubid = pub.pubid AND sub.artid = art.artid AND sub.dest_db LIKE @destination_db AND (sub.login_name = suser_sname(suser_sid()) OR is_srvrolemember('sysadmin') = 1 OR is_member ('db_owner') = 1) FOR READ ONLY OPEN hChelpsubscription_pub FETCH hChelpsubscription_pub INTO @subscriber, @publication, @destination_db, @pubid, @srvid, @immediate_sync WHILE (@@fetch_status <> -1) BEGIN /* ** Is it a full subscription ? i.e. Does it include all the articles? ** */ IF NOT EXISTS (SELECT * FROM sysarticles art WHERE art.pubid = @pubid and NOT EXISTS (SELECT * from syssubscriptions sub WHERE sub.artid = art.artid)) BEGIN /* Do all the subscriptions on the publication have same ** sync_type and subscription_type ? */ /* ** Get subscription type on the publication */ SELECT @subscription_type_id = subs.subscription_type, @sync_typeid = subs.sync_type FROM sysarticles art, syssubscriptions subs WHERE art.pubid = @pubid AND subs.srvid = @srvid AND subs.dest_db = @destination_db AND subs.artid = art.artid /* ** if the subscription all have the same subscription type ** and sync_type */ IF NOT EXISTS (SELECT * from sysarticles art, syssubscriptions subs where art.pubid = @pubid AND subs.srvid = @srvid AND subs.dest_db = @destination_db AND subs.artid = art.artid AND (subscription_type <> @subscription_type_id OR sync_type <> @sync_typeid)) SELECT @full_subscription = 1 ELSE SELECT @full_subscription = 0 END ELSE BEGIN SELECT @full_subscription = 0 END /* ** If it is a full subscription and the @article is 'all', ** only return one entry for the whole publication. ** Bug 22733: Always return one row per publication if @article is 'ALL' */ IF LOWER(@article) = 'all' BEGIN INSERT INTO #helpsubscription SELECT TOP 1 @subscriber, @publication, @article, @destination_db, sub.status, sub.sync_type, sub.subscription_type, @full_subscription, sub.distribution_jobid, @subscriber + ':' + @destination_db , -- SyncTran sub.update_mode, sub.loopback_detection -- end SyncTran FROM syssubscriptions sub, sysarticles art WHERE sub.srvid = @srvid AND sub.dest_db = @destination_db AND sub.artid = art.artid and art.pubid = @pubid END ELSE BEGIN /* ** Get subscriptions ** sa or dbo can see every subscriptions while ** others only see their own. */ INSERT INTO #helpsubscription SELECT @subscriber, @publication, art.name, @destination_db, sub.status, sub.sync_type, sub.subscription_type, @full_subscription, sub.distribution_jobid, @subscriber + ':' + @destination_db + ':' + art.name, -- SyncTran sub.update_mode, sub.loopback_detection -- end SyncTran FROM syssubscriptions sub, sysarticles art WHERE sub.srvid = @srvid AND sub.dest_db = @destination_db AND art.pubid = @pubid AND art.name LIKE @article AND sub.artid = art.artid AND (sub.login_name = suser_sname(suser_sid()) OR is_srvrolemember('sysadmin') = 1 OR is_member ('db_owner') = 1) END FETCH hChelpsubscription_pub INTO @subscriber, @publication, @destination_db, @pubid, @srvid, @immediate_sync END CLOSE hChelpsubscription_pub DEALLOCATE hChelpsubscription_pub /* ** Get subscriptions */ SELECT 'subscriber' = subscriber, 'publication' = publication, 'article' = article, 'destination database' = destination_db, 'subscription status' = status, 'synchronization type' = sync_type, 'subscription type' = subscription_type, 'full subscription' = full_subscription, 'subscription_name' = subscription_name, -- SyncTran 'update mode' = update_mode, 'distribution job id' = distribution_jobid, 'loopback_detection' = loopback_detection FROM #helpsubscription ORDER BY subscriber, publication, article go EXEC dbo.sp_MS_marksystemobject sp_helpsubscription GO print '' print 'Creating procedure sp_articlefilter' go create procedure sp_articlefilter @publication sysname, /* publication name */ @article sysname, /* article name */ @filter_name nvarchar (386) = NULL, /* name of filter procedure*/ @filter_clause ntext = NULL /* article's filter clause */ as declare @pubid smallint declare @table_name sysname declare @user_name sysname declare @qualified_table_name nvarchar (258) declare @filter_id int declare @type tinyint declare @previous_proc sysname declare @retcode int declare @site sysname declare @db sysname declare @owner sysname declare @object sysname declare @artid int declare @inactive tinyint declare @obid int select @inactive = 0 /* ** Security Check. */ exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Parameter Check: @publication. ** Make sure that the publication exists and that it conforms to the ** rules for identifiers. */ if @publication is null begin RAISERROR (14043, 16, -1, '@publication') return (1) END execute @retcode = dbo.sp_validname @publication if @retcode <> 0 RETURN (1) select @pubid = pubid from syspublications where name = @publication if @pubid is null begin RAISERROR (20026, 11, -1, @publication) return (1) end /* ** Parameter Check: @article. ** Check to make sure that the article exists in the publication. */ if @article is null begin RAISERROR (14043, 16, -1, '@article') return (1) end /* execute @retcode = dbo.sp_validname @article if @retcode <> 0 return (1) */ /* ** Get the article information. */ select @artid = art.artid, @table_name = so.name, @type = art.type, @filter_id = art.filter, @user_name = USER_NAME(so.uid) from sysarticles art, sysobjects so where art.pubid = @pubid and art.name = @article and art.objid = so.id /* ** Fail if there is no article information. */ if @artid is null begin RAISERROR (20027, 11, -1, @article) return (1) end /* ** Only unsubscribed articles may be modified. (excluding virtual subscriptions) */ if exists (select * from syssubscriptions where artid = @artid and status <> @inactive and srvid >= 0) begin RAISERROR (14092, 11, -1) RETURN (1) end /* ** Error out if this is a not a table based article */ IF NOT EXISTS ( SELECT * FROM sysarticles WHERE artid = @artid AND pubid = @pubid AND (type & 1) = 1 ) BEGIN RAISERROR (14112, 11, -1 ) RETURN (1) END /* ** Make sure a valid @filter_name was provided and it is ** a valid name. */ if datalength(@filter_clause) > 0 begin /* ** Make sure a valid @filter_name was provided and it is ** a valid name. */ if @filter_name is null begin RAISERROR (14043, 16, -1, '@filter_name') return (1) end select @object = PARSENAME( @filter_name, 1 ) select @owner = PARSENAME( @filter_name, 2 ) select @db = PARSENAME( @filter_name, 3 ) select @site = PARSENAME( @filter_name, 4 ) if @object IS NULL return 1 end /* ** If the article has a generated filter (not manually created), then ** drop the current filter before creating the new one. */ if ((@type & 0x3) <> 0x3) and @filter_id <> 0 begin select @previous_proc = object_name (@filter_id) if @previous_proc is not null and exists (select * from sysobjects where name = @previous_proc and type = 'RF') begin exec ('drop procedure ' + @previous_proc) if @@error <> 0 return (1) end end /* ** make an owner qualified table name for these operations name */ select @qualified_table_name = @user_name + '.' + @table_name -- Drop replication filter if it exists. -- Note: upgrade needs this logic if datalength(@filter_clause) > 0 and exists (select * from sysobjects where id = object_id(@object) and type = 'RF') begin exec ('drop procedure ' + @object) if @@error <> 0 return (1) end /* ** If there is a @filter_clause, create the new filter and ** update the article filter id and filter_clause. **/ if datalength(@filter_clause) > 0 begin exec ('create procedure ' + @object + ' for replication as ' + 'if exists (select * from ' + @qualified_table_name + ' where ' + @filter_clause + ') return 1 else return 0') if @@error <> 0 return (1) exec ('sp_MS_marksystemobject ''' + @object + '''') if @@error <> 0 return (1) select @filter_id = id from sysobjects where name = @object and type = 'RF' if @filter_id is null or @filter_id = 0 begin RAISERROR (15001, 11, -1, @object) return (1) end /* ** Update article */ update sysarticles set filter = @filter_id, filter_clause = @filter_clause where pubid = @pubid and name = @article ------------------------------------------------------------- -- SQL SERVER 7.0 ONLY: update sysobjects, set parent id = underlying -- object id ------------------------------------------------------------- select @obid = object_id( @qualified_table_name ) EXEC dbo.sp_MSsetfilterparent @object, @obid EXEC dbo.sp_MSsetfilteredstatus @obid end else BEGIN /* ** Clear the filter id and filter_clause. */ update sysarticles set filter = 0, filter_clause = NULL where pubid = @pubid and name = @article --------------------------------------------------- -- SQL SERVER 7.0 ONLY: remove parent_id from filter proc --------------------------------------------------- select @obid = object_id( @qualified_table_name ) if exists ( select * from sysobjects where name = @object and type = 'RF') EXEC dbo.sp_MSsetfilterparent @object, 0 EXEC dbo.sp_MSsetfilteredstatus @obid END /* ** Force the article cache to be refreshed with the new definition. */ EXECUTE dbo.sp_replflush go dump tran master with no_log go EXEC dbo.sp_MS_marksystemobject sp_articlefilter GO print '' print 'Creating procedure sp_MSarticletextcol' go CREATE PROCEDURE sp_MSarticletextcol ( @artid int, @colid smallint = NULL, @type nvarchar(10), /* 'publish', 'nonsqlsub' */ @operation nvarchar(5)) /* 'add', 'drop' */ AS /* ** Declarations. */ DECLARE @cmd nvarchar(255) DECLARE @cmd1 nvarchar(255) DECLARE @columns binary(32) /* Temporary storage for the converted column */ DECLARE @tabid int /* Article base table id */ DECLARE @retcode int DECLARE @status bit DECLARE @image tinyint /* Constant: 0x22 */ DECLARE @text tinyint /* Constant: 0x23 */ DECLARE @publish smallint /* Constant: 0x1000 */ DECLARE @nonsqlsub smallint /* Constant: 0x2000 */ DECLARE @tinycolid tinyint /* hydra compatible colid */ /* Constants */ SELECT @image = 0x22 SELECT @text = 0x23 SELECT @publish = 0x1000 SELECT @nonsqlsub = 0x2000 SELECT @tinycolid = @colid SELECT @tabid = objid FROM sysarticles WHERE artid = @artid IF @colid IS NULL BEGIN DECLARE hCarttextcol CURSOR LOCAL FAST_FORWARD FOR SELECT colid FROM syscolumns, sysarticles WHERE artid = @artid AND id = @tabid AND (syscolumns.type = 0x22 OR syscolumns.type = 0x23) AND convert(bit, convert( varbinary, substring( convert( nvarchar, columns ), 16 - floor((colid-1)/16),1 )) & power( 2, ((colid-1)%16))) = 1 END ELSE BEGIN DECLARE hCarttextcol CURSOR LOCAL FAST_FORWARD FOR SELECT colid FROM syscolumns WHERE id = @tabid AND colid = @colid AND (type = 0x22 OR type = 0x23) END /* Process each Text\Image column in the article */ OPEN hCarttextcol FETCH hCarttextcol INTO @colid WHILE (@@fetch_status <> -1) BEGIN IF LOWER(@operation) = 'add' BEGIN IF LOWER(@type) = 'publish' BEGIN UPDATE syscolumns SET colstat = colstat | @publish WHERE id = @tabid AND colid = @colid END ELSE BEGIN UPDATE syscolumns SET colstat = colstat | @nonsqlsub WHERE id = @tabid AND colid = @colid END END ELSE /* drop */ BEGIN /* ** Is there another non-sql server subscription on the column? ** Or another article publishing the column? */ EXEC @retcode = dbo.sp_MStextcolstatus @artid, @tabid, @colid, @type, @status OUTPUT IF @@error <> 0 OR @retcode <> 0 BEGIN CLOSE hCarttextcol DEALLOCATE hCarttextcol RETURN (1) END IF (@status = 0) BEGIN IF LOWER(@type) = 'publish' BEGIN /* Clear 'publish' bit */ UPDATE syscolumns SET colstat = colstat & ~@publish WHERE id = @tabid AND colid = @colid END ELSE BEGIN /* Clear 'non-sql server subscription' bit */ UPDATE syscolumns SET colstat = colstat & ~@nonsqlsub WHERE id = @tabid AND colid = @colid END END END FETCH hCarttextcol INTO @colid END CLOSE hCarttextcol DEALLOCATE hCarttextcol GO EXEC dbo.sp_MS_marksystemobject sp_MSarticletextcol GO print '' print 'Creating procedure sp_MStextcolstatus' go CREATE PROCEDURE sp_MStextcolstatus ( @artid int, @tabid int, @colid int, @type nvarchar (10), /* 'publish', 'nonsqlsub' */ @status bit OUTPUT) AS /* ** Declarations. */ DECLARE @cmd nvarchar(255) DECLARE @artid2 int DECLARE @columns binary(32) DECLARE @image tinyint /* Constant: 0x22 */ DECLARE @text tinyint /* Constant: 0x23 */ /* Constants */ SELECT @image = 0x22 SELECT @text = 0x23 SELECT @status = 0 IF LOWER(@type) = 'nonsqlsub' BEGIN /* ** Check all active or subscribed articles for the TEXT/IMAGE column. */ DECLARE hC4 CURSOR LOCAL FAST_FORWARD FOR SELECT sub.artid FROM sysarticles art, syssubscriptions sub WHERE art.objid = @tabid AND art.artid <> @artid AND sub.artid = art.artid AND sub.status = 1 OR sub.status = 2 END ELSE BEGIN /* ** Check all articles for the TEXT/IMAGE column. */ DECLARE hC4 CURSOR LOCAL FAST_FORWARD FOR SELECT artid FROM sysarticles WHERE objid = @tabid AND artid <> @artid END EXECUTE (@cmd) OPEN hC4 FETCH hC4 INTO @artid2 WHILE (@@fetch_status <> -1) BEGIN SELECT @columns = columns FROM sysarticles WHERE artid = @artid2 IF EXISTS (SELECT * FROM syscolumns WHERE id = @tabid AND colid = @colid AND CONVERT(bit, CONVERT( varbinary, SUBSTRING( CONVERT( nvarchar, @columns ), 16 - FLOOR((colid-1)/16),1 )) & POWER(2, ((colid-1)%16))) = 1 AND (type = @image OR type = @text)) BEGIN SELECT @status = 1 GOTO CLEANUP END FETCH hC4 INTO @artid2 END CLEANUP: CLOSE hC4 DEALLOCATE hC4 RETURN (0) GO EXEC dbo.sp_MS_marksystemobject sp_MStextcolstatus GO print '' print 'Creating procedure sp_articleview' go create procedure sp_articleview @publication sysname, /* Publication name */ @article sysname, /* Article name */ @view_name nvarchar (386) = NULL, /* View name */ @filter_clause ntext = NULL /* Article's filter clause */ as declare @pubid smallint declare @table_name sysname declare @user_id int declare @user_name sysname declare @qualified_table_name nvarchar (258) declare @columns varbinary (32) declare @name sysname /* ** NOTE: A column clause of 4000 characters can hold about 27 128- ** characters long column identifiers */ declare @col_clause nvarchar(4000) declare @retcode int declare @view_id int declare @type tinyint declare @table_id int declare @previous_view sysname declare @quoted_prev_view sysname declare @colid int declare @object sysname declare @quoted_object sysname declare @artid int declare @inactive tinyint select @inactive = 0 /* ** Security Check. */ exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Parameter Check: @publication. ** Make sure that the publication exists and that it conforms to the ** rules for identifiers. */ if @publication is null begin RAISERROR (14043, 16, -1, '@publication') return (1) END execute @retcode = dbo.sp_validname @publication if @retcode <> 0 RETURN (1) select @pubid = pubid from syspublications where name = @publication if @pubid is null begin RAISERROR (20026, 11, -1, @publication) return (1) end /* ** Parameter Check: @article. ** Check to make sure that the article exists in the publication. */ if @article is null begin RAISERROR (14043, 16, -1, '@article') return (1) end /* execute @retcode = dbo.sp_validname @article if @retcode <> 0 return (1) */ /* ** Get the article information. */ select @artid = art.artid, @table_name = so.name, @user_id = uid, @user_name = USER_NAME(so.uid), @columns = art.columns, @type = art.type, @view_id = art.sync_objid, @table_id = art.objid from sysarticles art, sysobjects so where art.pubid = @pubid and art.name = @article and art.objid = so.id /* ** Fail if there is no article information. */ if @artid is null begin RAISERROR (20027, 11, -1, @article) return (1) end /* ** Only unsubscribed articles may be modified. (excluding virtual subscriptions) */ if exists (select * from syssubscriptions where artid = @artid and status <> @inactive and srvid >= 0) begin RAISERROR (14092, 11, -1) RETURN (1) end /* ** Error out if this is a not a table based article */ IF NOT EXISTS ( SELECT * FROM sysarticles WHERE artid = @artid AND pubid = @pubid AND (type & 1) = 1 ) BEGIN RAISERROR (14112, 11, -1 ) RETURN (1) END /* ** Create a table of all the articles columns. */ create table #tmp (colid int NOT NULL, name sysname NOT NULL, published bit NOT NULL) if @@error <> 0 return (1) create unique index ind1 on #tmp (colid) if @@error <> 0 begin drop table #tmp return (1) end insert into #tmp select colid, name, convert(bit, convert( varbinary, substring( convert( nvarchar(16), @columns ), 16 - floor((colid-1)/16),1 )) & power( 2, ((colid-1)%16))) from syscolumns where id = (select id from sysobjects where name = @table_name and uid = @user_id and type = 'U') /* Break out the specified view name and get the non-ownerqual'd name, then validate that. */ select @object = PARSENAME( @view_name, 1 ) if @object IS NULL return 1 select @quoted_object = QUOTENAME(@object) execute @retcode = dbo.sp_validname @object if @retcode <> 0 return (1) /* If no non-published columns, we'll select all and avoid the 4000-char limit on column strings. */ if not exists (select * from #tmp where published = 0) begin select @col_clause = null goto CreateView end /* ** Construct the column list based on all published columns in the ** article. */ declare hC CURSOR LOCAL FAST_FORWARD FOR select colid, name from #tmp where published = 1 order by colid asc open hC fetch hC into @colid, @name /* ** Warning: A unicode character consists of two bytes! */ while (@@fetch_status <> -1) begin if @col_clause is null or ((len(@name) + len(@col_clause) + 2) <= 4000) if @col_clause is null select @col_clause = @name else select @col_clause = @col_clause + ', ' + @name else /* ** The procedure only support ~4000 characters for the column list */ begin RAISERROR (14039, 16, -1) close hC deallocate hC drop table #tmp return (1) end fetch hC into @colid, @name end close hC deallocate hC CreateView: /* ** If the article has a generated view (not manually created), then ** drop the current view before creating the new one. */ if ((@type & 0x5) <> 0x5) and @view_id <> 0 and @view_id <> @table_id begin select @previous_view = object_name (@view_id) if @previous_view is not null and exists (select * from sysobjects where name = @previous_view and type = 'V') begin select @quoted_prev_view = QUOTENAME(@previous_view) exec ('drop view ' + @quoted_prev_view) end end /* ** If a view is going to be created. Make sure a valid @view_name ** was provided. */ if @col_clause is not null begin if @view_name is null begin RAISERROR (14043, 16, -1, '@view_name') return (1) end end /* ** make an owner qualified table name for these operations name */ select @qualified_table_name = QUOTENAME(@user_name) + '.' + QUOTENAME(@table_name) /* ** Construct and execute the view creation command. */ -- Drop the existing view. -- Note: upgrade needs this logic if datalength(@filter_clause) > 0 and exists (select * from sysobjects where id = object_id(@object) and type = 'V') begin exec ('drop view ' + @quoted_object) if @@error <> 0 return (1) end if @col_clause is not null begin if datalength(@filter_clause) > 0 exec ('create view ' + @quoted_object + ' as select ' + @col_clause + ' from ' + @qualified_table_name + ' where ' + @filter_clause) else exec ('create view ' + @quoted_object + ' as select ' + @col_clause + ' from ' + @qualified_table_name) if @@error <> 0 return (1) end else begin if datalength(@filter_clause) > 0 begin exec ('create view ' + @quoted_object + ' as select * from ' + @qualified_table_name + ' where ' + @filter_clause) if @@error <> 0 return (1) end else begin exec ('create view ' + @quoted_object + ' as select * from ' + @qualified_table_name ) if @@error <> 0 return (1) end end ----------------------------------------------------------- -- Update the article's sync_objid with the new view id ----------------------------------------------------------- select @view_id = id from sysobjects where name = @object and type = 'V' if @view_id is null or @view_id = 0 begin RAISERROR (15001, 11, -1, @object) return (1) end else begin EXEC dbo.sp_MS_marksystemobject @object end --------------------------------------------- -- Update article definition -- Set new sync_objid and @filter_clause value --------------------------------------------- if datalength(@filter_clause) > 0 begin update sysarticles set sync_objid = @view_id, filter_clause = @filter_clause where pubid = @pubid and name = @article end else begin update sysarticles set sync_objid = @view_id, filter_clause = NULL where pubid = @pubid and name = @article end drop table #tmp /* ** Force the article cache to be refreshed with the new definition. */ EXECUTE dbo.sp_replflush go EXEC dbo.sp_MS_marksystemobject sp_articleview GO dump tran master with no_log go print '' print 'Creating procedure sp_MSaddexearticle' go CREATE PROCEDURE sp_MSaddexecarticle @publication sysname, /* publication name */ @article sysname, /* article name */ @source_proc nvarchar (92), /* table name */ @destination_proc sysname = NULL, /* destination table name */ @type sysname = NULL, /* article type */ @creation_script nvarchar (127) = NULL, /* article schema script */ @description nvarchar (255) = NULL, /* article description */ @pre_creation_cmd nvarchar(10) = 'drop', /* 'none', 'drop', 'delete', 'truncate' */ @schema_option binary(8) = NULL, /* script out stored procedure */ @destination_owner sysname, @article_id int OUTPUT AS SET NOCOUNT ON /* variables for SP_NAMECRACK */ DECLARE @site sysname DECLARE @db sysname DECLARE @owner sysname DECLARE @object sysname DECLARE @retcode int DECLARE @procid int DECLARE @procnum smallint DECLARE @pubid int DECLARE @precmdid int DECLARE @typeid smallint DECLARE @publish_bit smallint DECLARE @incompatible_typeid smallint DECLARE @cmd nvarchar(255) DECLARE @sysobj_colname sysname SELECT @typeid = 24 SELECT @sysobj_colname = 'replinfo' SELECT @publish_bit = 1 /* ** Parameter Check: @article. ** The @article name cannot be NULL and must conform to the rules ** for identifiers. */ IF @article IS NULL BEGIN RAISERROR (14043, 16, -1, '@article') RETURN (1) END /* EXECUTE @retcode = dbo.sp_validname @article IF @retcode <> 0 return(1) */ if LOWER(@article) = 'all' BEGIN RAISERROR (14032, 16, -1, '@article') RETURN (1) END /* ** Parameter Check: @publication. ** The @publication name cannot be NULL and must conform to the rules ** for identifiers. */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @retcode <> 0 RETURN (1) /* ** Parameter Check: @source_proc. ** Check to see that the @source_proc is local, that it conforms ** to the rules for identifiers, and that it is a procedure */ IF @source_proc IS NULL BEGIN RAISERROR (14043, 16, -1, '@source_proc') RETURN (1) END select @object = PARSENAME( @source_proc, 1 ) select @owner = PARSENAME( @source_proc, 2 ) select @db = PARSENAME( @source_proc, 3 ) select @site = PARSENAME( @source_proc, 4 ) if @object IS NULL return 1 IF @source_proc LIKE '%.%.%' AND @db <> DB_NAME() BEGIN RAISERROR (14004, 16, -1, @source_proc) RETURN (1) END /* ** Get the id of the @source_proc */ SELECT @procid = id FROM sysobjects WHERE id = OBJECT_ID(@source_proc) AND type = 'P' IF @procid IS NULL BEGIN RAISERROR (14027, 11, -1, @source_proc) RETURN (1) END IF EXISTS (SELECT * FROM syscomments WHERE id = @procid AND texttype = 4) BEGIN RAISERROR (21004, 16, -1, @source_proc) RETURN (1) END /* ** Parameter Check: @destination_proc. ** If the destination proc is not specified, assume it's the same ** as the source. Make sure that the name is not qualified. */ IF @destination_proc LIKE '%.%.%' BEGIN RAISERROR (14001, 16, -1) RETURN (1) END /* Enable owner qualified dest name IF @destination_proc LIKE '%.%' BEGIN RAISERROR (14044, 16, -1, '@destination_proc') RETURN (1) END */ IF @destination_proc IS NULL SELECT @destination_proc = @source_proc select @object = PARSENAME( @destination_proc, 1 ) select @owner = PARSENAME( @destination_proc, 2 ) select @db = PARSENAME( @destination_proc, 3 ) select @site = PARSENAME( @destination_proc, 4 ) if @object IS NULL return 1 /* ** Get the pubid. */ SELECT @pubid = pubid FROM syspublications WHERE name = @publication IF @pubid IS NULL BEGIN RAISERROR (14027, 11, -1, @publication) RETURN (1) END /* ** Parameter Check: @article, @publication. ** Check if the article already exists in this publication. */ IF EXISTS (SELECT * FROM sysarticles WHERE pubid = @pubid AND name = @article) BEGIN RAISERROR (14030, 16, -1, @article, @publication) RETURN (1) END /* ** Set the precmdid. The default type is 'drop'. ** ** @precmdid pre_creation_cmd ** ========= ================ ** 0 none ** 1 drop */ IF LOWER(@pre_creation_cmd) NOT IN ('none', 'drop') BEGIN RAISERROR (14111, 16, -1) RETURN (1) END /* ** Determine the integer value for the pre_creation_cmd. */ IF LOWER(@pre_creation_cmd) = 'none' SELECT @precmdid = 0 ELSE IF LOWER(@pre_creation_cmd) = 'drop' SELECT @precmdid = 1 /* Determine 'type' value for article. ** ** 8 proc exec ** 24 serializable proc exec */ IF @type IS NULL BEGIN SELECT @type = 'serializable proc exec' END ELSE IF LOWER(@type) NOT IN ('proc exec', 'serializable proc exec') BEGIN RAISERROR (14118, 16, -1) RETURN (1) END IF LOWER(@type) = 'proc exec' BEGIN SELECT @typeid = 8 SELECT @incompatible_typeid = 24 END ELSE IF LOWER(@type) = 'serializable proc exec' BEGIN SELECT @typeid = 24 SELECT @incompatible_typeid = 8 END -- make sure we haven't already created an article of a different type -- on this proc IF EXISTS ( select * from sysobjects where id = @procid and replinfo & @incompatible_typeid = @incompatible_typeid ) BEGIN RAISERROR (21024, 16, -1, @source_proc ) RETURN(1) END /* ** Parameter Check: @creation_script and @schema_option ** @schema_option is null, set the default value ** If @schema_option is 0, there have to be @creation_script defined. */ IF @schema_option IS NULL BEGIN SELECT @schema_option = 1 /* RAISERROR (14043, 16, -1, '@schema_option') RETURN (1) */ END IF @schema_option <> 0x0000000000000000 AND @schema_option <> 0x0000000000000001 BEGIN RAISERROR (20014, 10, -1) RETURN (1) END /* ** Add article to sysarticles and update sysobjects category bit. */ begin tran save TRAN sp_MSaddexecarticle INSERT sysarticles (columns, creation_script, del_cmd, description, dest_table, filter, filter_clause, ins_cmd, name, objid, pre_creation_cmd, pubid, status, sync_objid, type, upd_cmd, schema_option, dest_owner) VALUES (0, @creation_script, NULL, @description, @destination_proc, 0, '', NULL, @article, @procid, @precmdid, @pubid, 0, @procid, @typeid, NULL, @schema_option, @destination_owner) IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_MSaddexecarticle commit tran end RETURN (1) END SELECT @article_id = @@IDENTITY select @cmd = 'UPDATE sysobjects SET ' + @sysobj_colname select @cmd = @cmd + ' = ' + @sysobj_colname + ' | ' + CONVERT( nvarchar, @publish_bit ) select @cmd = @cmd + ' WHERE id = (SELECT objid FROM sysarticles WHERE name = ''' select @cmd = @cmd + @article + ''' and pubid = ' + CONVERT( nvarchar, @pubid ) + ')' EXEC (@cmd) IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_MSaddexecarticle commit tran end RETURN (1) END COMMIT TRAN go EXEC dbo.sp_MS_marksystemobject sp_MSaddexecarticle GO print '' print 'Creating procedure sp_addarticle' go CREATE PROCEDURE sp_addarticle @publication sysname, /* publication name */ @article sysname, /* article name */ @source_table nvarchar (386) = NULL, /* table name */ @destination_table sysname = NULL, /* destination table name */ @vertical_partition nchar(5) = 'false', /* vertical partition */ @type sysname = NULL, /* article type */ @filter nvarchar (386) = NULL, /* stored procedure used to filter table */ @sync_object nvarchar (386) = NULL, /* view or table used for synchronization */ @ins_cmd nvarchar (255) = NULL, /* insert format string */ @del_cmd nvarchar (255) = NULL, /* delete format string */ @upd_cmd nvarchar (255) = NULL, /* update format string */ @creation_script nvarchar (127) = NULL, /* article schema script */ @description nvarchar (255) = NULL, /* article description */ @pre_creation_cmd nvarchar(10) = 'drop', /* 'none', 'drop', 'delete', 'truncate' */ @filter_clause ntext = NULL, /* where clause */ @schema_option binary(8) = NULL, @destination_owner sysname = NULL, @status tinyint = 16, /* Default: binary command format */ @source_owner sysname = NULL, /* NULL for 6.5 users, not NULL for 7.0 users */ @sync_object_owner sysname = NULL, /* NULL for 6.5 users, not NULL for 7.0 users */ @filter_owner sysname = NULL, /* NULL for 6.5 users, not NULL for 7.0 users */ @source_object sysname = NULL /* if @source_table is NULL, this parameter can not be NULL */ AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @bak_source sysname DECLARE @num_columns int DECLARE @accessid smallint DECLARE @db sysname DECLARE @filterid int DECLARE @object sysname DECLARE @owner sysname DECLARE @pubid int DECLARE @publish_bit smallint DECLARE @retcode int DECLARE @site sysname DECLARE @syncid int DECLARE @tabid int DECLARE @typeid smallint DECLARE @pkkey sysname DECLARE @i int DECLARE @indid int DECLARE @precmdid int DECLARE @object_type nchar(2) DECLARE @push tinyint DECLARE @dbname sysname DECLARE @cmd nvarchar(255) DECLARE @fHasPk int DECLARE @no_sync tinyint DECLARE @immediate_sync bit DECLARE @is_filter_in_use int DECLARE @distributor sysname DECLARE @distribdb sysname DECLARE @distproc nvarchar (255) DECLARE @article_id int DECLARE @sync_method tinyint -- SyncTran DECLARE @autogen_sync_procs_id int DECLARE @custom_proc_name varchar(32) DECLARE @guid varbinary(16) declare @allow_sync_tran bit SELECT @push = 0 SELECT @dbname = DB_NAME() SELECT @publish_bit = 1 SELECT @no_sync = 2 /* no sync type in syssubscriptions */ /* ** Security Check. */ exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Parameter Check: @article. ** The @article name cannot be NULL and must conform to the rules ** for identifiers. */ IF @article IS NULL BEGIN RAISERROR (14043, 16, -1, '@article') RETURN (1) END exec @retcode = dbo.sp_MSreplcheck_name @article if @@ERROR <> 0 or @retcode <> 0 return(1) if LOWER(@article) = 'all' BEGIN RAISERROR (14032, 16, -1, '@article') RETURN (1) END /* ** Parameter Check: @publication. ** The @publication name cannot be NULL and must conform to the rules ** for identifiers. */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @retcode <> 0 RETURN (1) /* ** Parameter Check: @destination_owner. ** The @destination_owner must conform to the rules ** for identifiers. */ if @destination_owner is not null BEGIN -- native bcp mode publications are for odbc subscribers. Destination -- owner name is not supported. if exists (select * from syspublications where name = @publication and sync_method = 1) begin raiserror(21039,16, -1) return(1) end EXECUTE @retcode = dbo.sp_validname @destination_owner IF @retcode <> 0 RETURN (1) END /* ** Parameter Check: @source_table. ** Check to see that the @source_table is local, that it conforms ** to the rules for identifiers, and that it is a table, and not ** a view or another database object. */ IF @source_table IS NULL BEGIN if @source_object is NOT NULL select @source_table = @source_object else begin RAISERROR (14043, 16, -1, '@source_table') RETURN (1) end END IF @source_owner is NULL -- 6.5 users only begin IF @source_table LIKE '%.%.%' AND PARSENAME(@source_table, 3) <> DB_NAME() BEGIN RAISERROR (14004, 16, -1, @source_table) RETURN (1) END end -- For 7.0 users, @source_owner is not nullable. select @bak_source = @source_table IF @source_owner is not NULL begin select @source_table = QUOTENAME(@source_owner) + '.' + QUOTENAME(@source_table) IF @destination_table IS NULL SELECT @destination_table = @bak_source end ELSE IF @destination_table IS NULL -- Set destination_table if not provided or default by now. -- If @source_table is qualified (6.x behavior) only use table name for destination name. SELECT @destination_table = PARSENAME(@source_table, 1) select @num_columns=count(*) from syscolumns where id = object_id(@source_table) if @num_columns > 255 begin RAISERROR (20068, 16, @source_table, 255) RETURN (1) end /* ** Get the id of the @source_table */ SELECT @tabid = id, @object_type = type FROM sysobjects WHERE id = OBJECT_ID(@source_table) IF @tabid IS NULL BEGIN RAISERROR (14027, 11, -1, @source_table) RETURN (1) END -- at this point, we've done all the common parameter checks. -- If this is a procedure, branch to the proc execution publishing -- routine, otherwise continue processing as if it were a table IF @object_type = 'P' BEGIN begin tran save TRAN sp_addarticle EXECUTE @retcode = dbo.sp_MSaddexecarticle @publication, @article, @source_table, @destination_table, @type, @creation_script, @description, @pre_creation_cmd, @schema_option, @destination_owner, @article_id OUTPUT IF @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END ELSE GOTO DONE END /* ** Make sure that the table name specified is a table and not a view. */ IF NOT EXISTS (SELECT * FROM sysobjects WHERE id = (SELECT OBJECT_ID(@source_table)) AND type = 'U') BEGIN RAISERROR (14028, 16, -1) RETURN (1) END /* ** Parameter Check: @destination_table. ** If the destination table is not specified, assume it's the same ** as the source table. Make sure that the table name is not qualified. */ IF @destination_table LIKE '%.%.%' BEGIN RAISERROR (14001, 16, -1) RETURN (1) END IF @destination_table LIKE '%.%' BEGIN RAISERROR (14044, 16, -1, '@destination_table') RETURN (1) END /* ** Parameter Check: @vertical_partition ** Check to make sure that the vertical partition is either TRUE or FALSE. */ SELECT @vertical_partition = LOWER(@vertical_partition) IF @vertical_partition NOT IN ('true', 'false') BEGIN RAISERROR (14029, 16, -1) RETURN (1) END -- -- parameter check: @status -- IF (@status & ~24 ) <> 0 BEGIN RAISERROR( 21061, 16, -1, @status, @article ) RETURN (1) END /* ** Parameter Check: @filter ** Make sure that the filter is a valid stored procedure. */ IF @filter IS NOT NULL BEGIN IF @filter_owner IS NULL BEGIN select @object = PARSENAME( @filter, 1 ) select @owner = PARSENAME( @filter, 2 ) select @db = PARSENAME( @filter, 3 ) select @site = PARSENAME( @filter, 4 ) if @object IS NULL return 1 END ELSE BEGIN select @filter = QUOTENAME(@filter_owner) + '.' + QUOTENAME(@filter) END /* ** Get the id of the @filter */ select @filterid = id from sysobjects where id = OBJECT_ID(@filter) and type = 'RF' IF @filterid IS NULL BEGIN RAISERROR (14027, 11, -1, @filter) RETURN (1) END EXEC @is_filter_in_use = dbo.sp_MSdoesfilterhaveparent @filterid if( @is_filter_in_use <> 0 ) BEGIN RAISERROR( 21009, 11, -1 ) RETURN (1) END END ELSE select @filterid = 0 /* ** Get the pubid. */ -- SyncTran -- SELECT @pubid = pubid FROM syspublications WHERE name = @publication SELECT @pubid = pubid, @autogen_sync_procs_id = autogen_sync_procs, @sync_method = sync_method, @allow_sync_tran = allow_sync_tran FROM syspublications WHERE name = @publication -- end SyncTran IF @pubid IS NULL BEGIN RAISERROR (14027, 11, -1, @publication) RETURN (1) END /* ** Parameter Check: @article, @publication. ** Check if the article already exists in this publication. */ IF EXISTS (SELECT * FROM sysarticles WHERE pubid = @pubid AND name = @article) BEGIN RAISERROR (14030, 16, -1, @article, @publication) RETURN (1) END /* ** Set the typeid. The default type is logbased. Anything else is ** currently undefined (reserved for future use). ** ** @typeid type ** ======= ======== ** 1 logbased ** 3 logbased manualfilter ** 5 logbased manualview ** 7 logbased manualboth ** 8 proc exec (valid in dbo.sp_MSaddexecarticle) ** 24 serializable proc exec (valid in dbo.sp_MSaddexecarticle) */ IF @type IS NULL BEGIN SELECT @type = 'logbased' END ELSE IF LOWER(@type) NOT IN ('logbased', 'logbased manualfilter', 'logbased manualview', 'logbased manualboth') BEGIN RAISERROR (14023, 16, -1) RETURN (1) END IF LOWER(@type) = 'logbased' SELECT @typeid = 1 ELSE IF LOWER(@type) = 'logbased manualfilter' SELECT @typeid = 3 ELSE IF LOWER(@type) = 'logbased manualview' SELECT @typeid = 5 ELSE IF LOWER(@type) = 'logbased manualboth' SELECT @typeid = 7 /* ** Set the precmdid. The default type is 'drop'. ** ** @precmdid pre_creation_cmd ** ========= ================ ** 0 none ** 1 drop ** 2 delete ** 3 truncate */ IF LOWER(@pre_creation_cmd) NOT IN ('none', 'drop', 'delete', 'truncate') BEGIN RAISERROR (14061, 16, -1) RETURN (1) END /* ** Determine the integer value for the pre_creation_cmd. */ IF LOWER(@pre_creation_cmd) = 'none' SELECT @precmdid = 0 ELSE IF LOWER(@pre_creation_cmd) = 'drop' SELECT @precmdid = 1 ELSE IF LOWER(@pre_creation_cmd) = 'delete' SELECT @precmdid = 2 ELSE IF LOWER(@pre_creation_cmd) = 'truncate' SELECT @precmdid = 3 IF @sync_object IS NULL select @syncid = @tabid ELSE BEGIN IF @sync_object_owner is NULL -- 6.5 only BEGIN /* ** Parameter Check: @sync_object. ** Check to see that the sync_object is local and that it ** conforms to the rules for identifiers. */ select @object = PARSENAME( @sync_object, 1 ) select @owner = PARSENAME( @sync_object, 2 ) select @db = PARSENAME( @sync_object, 3 ) select @site = PARSENAME( @sync_object, 4 ) if @object IS NULL return 1 IF @sync_object LIKE '%.%.%' AND @db <> DB_NAME() BEGIN RAISERROR (14004, 16, -1, @sync_object) RETURN (1) END END -- end of 65 processing else -- for sphinx, @sync_object_owner can not be null select @sync_object = QUOTENAME(@sync_object_owner) + '.' + QUOTENAME(@sync_object) /* ** Get the id of the @sync_object */ SELECT @syncid = id FROM sysobjects WHERE id = OBJECT_ID(@sync_object) IF @syncid IS NULL BEGIN RAISERROR (14027, 11, -1, @sync_object) RETURN (1) END /* ** Make sure the sync object specified is a table or a view. */ IF NOT EXISTS (SELECT * FROM sysobjects WHERE id = (SELECT OBJECT_ID(@sync_object)) AND (type = 'U' or type = 'V')) BEGIN RAISERROR (14031, 16, -1) RETURN (1) END END /* ** If the publication is log-based, ** make sure there is a primary key on the source table. ** NOTE! sprok in SPSUP.SQL */ IF EXISTS (SELECT * FROM syspublications WHERE pubid = @pubid AND (repl_freq = 0 OR allow_sync_tran = 1) ) BEGIN EXEC @fHasPk = dbo.sp_MSreplsup_table_has_pk @tabid IF @fHasPk = 0 BEGIN RAISERROR (14088, 16, -1, @source_table) RETURN (1) END END /* ** Parameter Check: @creation_script and @schema_option ** @schema_option cannot be null ** If @schema_option is 0, there have to be @creation_script defined. */ IF @schema_option IS NULL BEGIN SELECT @schema_option = 0x0000000000000073 END -- If pub sync_type is character mode bcp(1) if @sync_method = 1 begin select @status = 0 if @ins_cmd is NULL select @ins_cmd = 'SQL' if @upd_cmd is NULL select @upd_cmd = 'SQL' if @del_cmd is NULL select @del_cmd = 'SQL' end /* ** Parameter Check: @schema_option ** If Autogeneration of custom procedures is not enabled ** then the default commands will be SQL */ IF ((CONVERT(int, @schema_option) & 0x2) = 0) BEGIN if @ins_cmd is NULL select @ins_cmd = 'SQL' if @upd_cmd is NULL select @upd_cmd = 'SQL' if @del_cmd is NULL select @del_cmd = 'SQL' END -- Autogenerate custom procedure names if not provided. -- If unable to construct a name because the article name is close to the maximum length, then create a -- name based on the database timestamp if ((@source_object is not NULL and len(@article) > 119) or (@source_object is NULL and len(@article) > 21)) begin set @guid = CONVERT(varbinary(16), LEFT(NEWID(),8)) exec @retcode = master.dbo.xp_varbintohexstr @guid, @custom_proc_name OUTPUT if @@error <> 0 or @retcode <> 0 RETURN(1) end else set @custom_proc_name = @article -- If no command then construct name if @ins_cmd is NULL begin if (@status & 16) <> 0 -- parameterized begin if @source_object is not NULL -- 7.0 format set @ins_cmd = N'CALL ' + convert (sysname, 'sp_MSins_' + @custom_proc_name) else -- 6.x compatible set @ins_cmd = N'CALL ' + convert(nvarchar(30), 'sp_MSins_' + @custom_proc_name) end else select @ins_cmd = 'SQL' end if @del_cmd is NULL begin if (@status & 16) <> 0 -- parameterized begin if @source_object is not NULL -- 7.0 format set @del_cmd = N'CALL ' + convert (sysname, 'sp_MSdel_' + @custom_proc_name) else -- 6.x compatible set @del_cmd = N'CALL ' + convert(nvarchar(30), 'sp_MSdel_' + @custom_proc_name) end else select @del_cmd = 'SQL' end if @upd_cmd is NULL begin if (@status & 16) <> 0 -- parameterized begin if @source_object is not NULL -- 7.0 format set @upd_cmd = N'MCALL ' + convert (sysname, 'sp_MSupd_' + @custom_proc_name) else -- 6.x compatible set @upd_cmd = N'CALL ' + convert(nvarchar(30), 'sp_MSupd_' + @custom_proc_name) end else select @upd_cmd = 'SQL' end -- SyncTran -- Add timestamp column if not exists if @allow_sync_tran = 1 and ObjectProperty(@tabid, 'TableHasTimestamp') = 0 begin exec ('alter table ' + @source_table + ' add msrepl_synctran_ts timestamp not null' ) IF @@ERROR <> 0 RETURN (1) end /* ** Add article to sysarticles and update sysobjects category bit. */ begin tran save TRAN sp_addarticle INSERT sysarticles (columns, creation_script, del_cmd, description, dest_table, filter, filter_clause, ins_cmd, name, objid, pre_creation_cmd, pubid, status, sync_objid, type, upd_cmd, schema_option, dest_owner) VALUES (0, @creation_script, @del_cmd, @description, @destination_table, @filterid, @filter_clause, @ins_cmd, @article, @tabid, @precmdid, @pubid, @status, @syncid, @typeid, @upd_cmd, @schema_option, @destination_owner) IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END SELECT @article_id = @@IDENTITY UPDATE sysobjects SET replinfo = replinfo | @publish_bit WHERE id = (SELECT objid FROM sysarticles WHERE name = @article and pubid = @pubid) IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END IF @filter IS NOT NULL BEGIN EXEC dbo.sp_MSsetfilterparent @filter, @tabid IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END END EXEC dbo.sp_MSsetfilteredstatus @tabid IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END /* ** Set all bits to '1' in the columns column to include all columns. */ IF @vertical_partition = 'false' BEGIN EXECUTE @retcode = dbo.sp_articlecolumn @publication, @article -- synctran , @refresh_synctran_procs = 0 IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END END /* ** 1. Set all bits to '1' for all columns in the primary key. ** 2. Set timestamp column bit to 1 if the publication is synctran */ ELSE BEGIN SELECT @indid = indid FROM sysindexes WHERE id = @tabid AND (status & 2048) <> 0 /* PK index */ /* ** First we'll figure out what the keys are. */ SELECT @i = 1 WHILE (@i <= 16) BEGIN SELECT @pkkey = INDEX_COL(@source_table, @indid, @i) if @pkkey is NULL break EXECUTE @retcode = dbo.sp_articlecolumn @publication, @article, @pkkey, 'add' -- synctran , @refresh_synctran_procs = 0 IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END select @i = @i + 1 END if @allow_sync_tran = 1 and ObjectProperty(@tabid, 'TableHasTimestamp') = 1 begin declare @ts_col sysname -- Get synctran column select @ts_col = name from syscolumns where id = @tabid and type_name(xtype) = 'timestamp' if @ts_col is not null begin EXECUTE @retcode = dbo.sp_articlecolumn @publication, @article, @ts_col, 'add' -- synctran , @refresh_synctran_procs = 0 IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END end end END ------------------------------------------------------------------------------ -- if table based article does not use a view for sync, create one and use it ------------------------------------------------------------------------------ if @tabid = @syncid begin -- generate view name declare @viewname varchar(255) set @guid = CONVERT(varbinary(16), LEFT(NEWID(),8)) exec @retcode = master.dbo.xp_varbintohexstr @guid, @viewname OUTPUT if @@ERROR <> 0 OR @retcode <> 0 begin if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end return 1 end set @viewname = 'syncobj_' + @viewname -- create view for object synchronization exec @retcode = dbo.sp_articleview @publication, @article, @viewname, @filter_clause if @@ERROR <> 0 OR @retcode <> 0 begin if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end return 1 end end DONE: /* ** Get distribution server information for remote RPC call. */ EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distribdb OUTPUT IF @@ERROR <> 0 or @retcode <> 0 BEGIN RAISERROR (14071, 16, -1) RETURN (1) END SELECT @dbname = DB_NAME() SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + '.dbo.sp_MSadd_article' EXECUTE @retcode = @distproc @publisher = @@SERVERNAME, @publisher_db = @dbname, @publication = @publication, @article = @article, @article_id = @article_id, @destination_object = @destination_table, @source_owner = @source_owner, @source_object = @bak_source, @description = @description IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END /* If the publication is immediate_sync type ** 1. Change the immediate_sync_ready status to false ** 2. Add a virtual subscription on the article ** 3. Add subscriptions for all the subscriber ** that have no_sync subscriptions on the publication ** ** Note: Subscriptions for subscribers that have automatic sync subscriptions ** on the publication will be added by snasphot agent. */ if EXISTS (SELECT * FROM syspublications WHERE name = @publication AND immediate_sync = 1 ) BEGIN UPDATE syspublications SET immediate_sync_ready = 0 WHERE name = @publication IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END EXECUTE @retcode = dbo.sp_addsubscription @publication = @publication, @article = @article, @subscriber = NULL, @destination_db = 'virtual', @sync_type = 'automatic', @status = NULL, @reserved = 'internal' IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END -- Note: We have to add the subscriptions to the new article before -- the virtual subscriptions being activated!!!! Otherwise, the snapshot -- transactions may be skipped by dist agents. EXECUTE @retcode = dbo.sp_refreshsubscriptions @publication IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_addarticle commit tran end RETURN (1) END END /* ** if @autogen_sync_procs_id is 1, autogen the sync tran procs, including name */ if @tabid > 0 and @autogen_sync_procs_id = 1 begin declare @insproc sysname, @updproc sysname, @delproc sysname select @insproc = 'sp_MSsync_ins_' + SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @pubid)) select @updproc = 'sp_MSsync_upd_' + SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @pubid)) select @delproc = 'sp_MSsync_del_' + SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @pubid)) -- check uniqueness of names and revert to ugly guid-based name if friendly name already exists if exists (select name from sysobjects where name in (@insproc, @updproc, @delproc)) begin declare @guid_name nvarchar(36) select @guid_name = convert (nvarchar(36), newid()) -- remove '-' from guid name because rpc can't handle '-' select @guid_name = replace (@guid_name,'-','_') select @insproc = 'sp_MSsync_ins_' + @guid_name select @updproc = 'sp_MSsync_upd_' + @guid_name select @delproc = 'sp_MSsync_del_' + @guid_name end if @insproc IS NULL begin if @@trancount > 0 begin ROLLBACK TRANSACTION sp_addarticle commit tran end RAISERROR (14043, 11, -1, '@insproc') RETURN (1) end if @updproc IS NULL begin if @@trancount > 0 begin ROLLBACK TRANSACTION sp_addarticle commit tran end RAISERROR (14043, 11, -1, '@updproc') RETURN (1) end if @delproc IS NULL begin if @@trancount > 0 begin ROLLBACK TRANSACTION sp_addarticle commit tran end RAISERROR (14043, 11, -1, '@delproc') RETURN (1) end exec @retcode = dbo.sp_articlesynctranprocs @publication, @article, @insproc, @updproc, @delproc, true IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRANSACTION sp_addarticle commit tran end RETURN (1) END end -- end SyncTran COMMIT TRANSACTION go /* ** Create replication stored procedures. ** Part 1: create codependent procedures. */ EXEC dbo.sp_MS_marksystemobject sp_addarticle GO print '' print 'Creating procedure sp_changesubstatus' go CREATE PROCEDURE sp_changesubstatus ( @publication sysname = '%', /* publication name */ @article sysname = '%', /* article name */ @subscriber sysname = '%', /* subscriber name */ @status sysname, /* subscription status */ @previous_status sysname=NULL, /* previous subscription status */ @destination_db sysname = '%', /* destination database name */ @frequency_type int = NULL, @frequency_interval int = NULL, @frequency_relative_interval int = NULL, @frequency_recurrence_factor int = NULL, @frequency_subday int = NULL, @frequency_subday_interval int = NULL, @active_start_time_of_day int = NULL, @active_end_time_of_day int = NULL, @active_start_date int = NULL, @active_end_date int = NULL, @optional_command_line nvarchar(4000) = NULL, @distribution_jobid binary(16) = NULL OUTPUT, @from_auto_sync bit = 0, @ignore_distributor bit = 0 ) AS SET NOCOUNT ON DECLARE @inactive tinyint DECLARE @subscribed tinyint DECLARE @active tinyint DECLARE @public tinyint DECLARE @replicate_bit smallint DECLARE @msg nvarchar(255) DECLARE @prevstatid tinyint DECLARE @artid int DECLARE @tabid int DECLARE @srvid smallint DECLARE @statusid tinyint DECLARE @distributor sysname DECLARE @distribdb sysname DECLARE @distproc nvarchar (255) DECLARE @pub_db sysname DECLARE @dest_db sysname DECLARE @sub_name sysname DECLARE @sub_status tinyint DECLARE @sub_ts varbinary (16) DECLARE @non_sql_flag bit DECLARE @cmd0 nvarchar (255) DECLARE @cmd1 nvarchar (255) DECLARE @cmd2 nvarchar (255) DECLARE @cmd3 nvarchar (255) DECLARE @retcode int DECLARE @repl_freq tinyint DECLARE @art_type tinyint DECLARE @proccmd nvarchar(255) DECLARE @procnum smallint DECLARE @finished_real bit DECLARE @finished_virtual bit DECLARE @virtual_id smallint DECLARE @immediate_sync bit DECLARE @enabled_for_internet bit DECLARE @allow_anonymous bit DECLARE @subscription_type int DECLARE @xact_seqno binary(10) DECLARE @sync_type tinyint DECLARE @automatic tinyint DECLARE @art_change bit declare @login_name sysname -- synctran DECLARE @update_mode tinyint DECLARE @art_name sysname declare @synctran tinyint declare @no_distproc bit declare @loopback_detection bit /* ** Initializations. */ select @synctran = 1 SELECT @automatic = 1 SELECT @inactive = 0 /* Const: subscription status 'inactive' */ SELECT @subscribed = 1 /* Const: subscription status 'subscribed' */ SELECT @active = 2 /* Const: subscription status 'active' */ SELECT @public = 0 /* Const: publication status 'public' */ SELECT @pub_db = DB_NAME() SELECT @virtual_id = -1 SELECT @art_change = 0 SELECT @replicate_bit = 2 /* ** Security Check. ** We use login_name stored in syssubscriptions to manage security */ /* ** Parameter Check: @publication ** Check to make sure that the publication exists, that it's not NULL, ** and that it conforms to the rules for identifiers. */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END IF @publication <> '%' BEGIN EXECUTE @retcode = dbo.sp_validname @publication IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) END IF NOT EXISTS (SELECT * FROM syspublications WHERE name LIKE @publication) BEGIN IF @publication = '%' RAISERROR (14008, 11, -1) ELSE RAISERROR (20026, 11, -1, @publication) RETURN (1) END /* ** Parameter Check: @article ** Check to make sure that the article exists, that it's not null, ** and that it conforms to the rules for identifiers. */ IF @article IS NULL BEGIN RAISERROR (14043, 16, -1, '@article') RETURN (1) END /* IF @article <> '%' BEGIN EXECUTE @retcode = dbo.sp_validname @article IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) END */ IF NOT EXISTS (SELECT * FROM sysarticles a, syspublications b WHERE a.name LIKE @article AND a.pubid = b.pubid AND b.name LIKE @publication) BEGIN IF @article = '%' RAISERROR (14009, 11, -1, @publication) ELSE RAISERROR (20027, 11, -1, @article) RETURN (1) END /* ** Parameter Check: @subscriber ** Check to make sure that the subscriber exists, that it is not NULL, ** and that it conforms to the rules for identifiers. ** Null subscriber represents virtual subscriptions */ IF @subscriber IS NOT NULL AND @subscriber <> '%' BEGIN EXECUTE @retcode = dbo.sp_validname @subscriber IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) IF NOT EXISTS (SELECT * FROM master..sysservers WHERE UPPER(srvname) = UPPER(@subscriber) AND (srvstatus & 4) <> 0) BEGIN RAISERROR (14063, 11, -1) RETURN (1) END END /* ** Parameter Check: @status. ** Set the @statusid according to the @status value. Values can be ** any of the following: ** ** status statusid ** ========= ======== ** inactive 0 ** subscribed 1 ** active 2 */ IF LOWER(@status) NOT IN ('active', 'subscribed', 'inactive') BEGIN RAISERROR (14065, 16, -1) RETURN (1) END IF LOWER(@status) IN ('active') SELECT @statusid = @active ELSE IF LOWER(@status) IN ('subscribed') SELECT @statusid = @subscribed ELSE SELECT @statusid = @inactive /* ** Parameter Check: @previous_status. ** Set the @prevstatid according to the @previous_status value. ** Values can be any of the following: ** ** previous_status prevstatid ** =============== ========== ** inactive 0 ** subscribed 1 ** active 2 */ IF @previous_status IS NOT NULL BEGIN IF LOWER(@previous_status) NOT IN ('active', 'subscribed', 'inactive') BEGIN RAISERROR (14066, 16, -1) RETURN (1) END IF LOWER(@status) = LOWER(@previous_status) BEGIN RAISERROR (14067, 16, -1) RETURN (1) END IF LOWER(@previous_status) IN ('active') SELECT @prevstatid = @active ELSE IF LOWER(@previous_status) IN ('subscribed') SELECT @prevstatid = @subscribed ELSE SELECT @prevstatid = @inactive END /* ** Parameter Check: @destination_db. ** Set @destination_db to current database if not specified. Make ** sure that the @destination_db conforms to the rules for identifiers. */ IF @destination_db <> '%' BEGIN EXECUTE @retcode = dbo.sp_validname @destination_db IF @retcode <> 0 RETURN (1) END /* ** Get distribution server information for remote RPC ** subscription calls. ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC. */ if @ignore_distributor = 1 select @no_distproc = 1 else select @no_distproc = 0 IF @no_distproc = 0 and @from_auto_sync = 0 BEGIN EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distribdb OUTPUT IF @@ERROR <> 0 BEGIN RAISERROR (14071, 16, -1) RETURN (1) END IF @retcode <> 0 OR @distribdb IS NULL OR @distributor IS NULL BEGIN RAISERROR (14071, 16, -1) RETURN (1) END END begin tran save TRANSACTION changesubstatus SELECT @finished_virtual = 0 SELECT @finished_real = 0 /* ** If @subscriber is null, don't process real subscriptions ** If @subscriber is not null and '%', don't process virtual subscriptions */ IF @subscriber IS NULL SELECT @finished_real = 1 ELSE IF @subscriber <> '%' SELECT @finished_virtual = 1 WHILE (@finished_real = 0 OR @finished_virtual = 0) BEGIN /* ** Declare cursor containing subscriptions to be updated. */ IF @finished_real = 0 BEGIN IF @previous_status IS NOT NULL BEGIN DECLARE hCsubstatus CURSOR LOCAL SCROLL_LOCKS FOR SELECT sub.artid, art.objid, sub.srvid, ss.srvname, sub.dest_db, sub.status, case when ss.srvproduct = 'MSREPL-NONSQL' then 1 else 0 end, pub.repl_freq, art.type, pub.immediate_sync, pub.enabled_for_internet, pub.allow_anonymous, sub.subscription_type, sub.sync_type, sub.update_mode, art.name, sub.login_name, sub.loopback_detection FROM syssubscriptions sub, sysarticles art, syspublications pub, master..sysservers ss WHERE pub.name LIKE @publication AND art.name LIKE @article AND ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber))) AND sub.srvid = ss.srvid AND sub.artid = art.artid AND art.pubid = pub.pubid AND sub.status = @prevstatid AND sub.dest_db LIKE @destination_db END ELSE BEGIN DECLARE hCsubstatus CURSOR LOCAL SCROLL_LOCKS FOR SELECT sub.artid, art.objid, sub.srvid, ss.srvname, sub.dest_db, sub.status, case when ss.srvproduct = 'MSREPL-NONSQL' then 1 else 0 end, pub.repl_freq, art.type, pub.immediate_sync, pub.enabled_for_internet, pub.allow_anonymous, sub.subscription_type, sub.sync_type, sub.update_mode, art.name, sub.login_name, sub.loopback_detection FROM syssubscriptions sub, sysarticles art, syspublications pub, master..sysservers ss WHERE pub.name LIKE @publication AND art.name LIKE @article AND ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber))) AND sub.srvid = ss.srvid AND sub.artid = art.artid AND art.pubid = pub.pubid AND sub.dest_db LIKE @destination_db END SELECT @finished_real = 1 END ELSE IF @finished_virtual = 0 BEGIN DECLARE @sub_bit smallint DECLARE @null_name sysname SELECT @sub_bit = 4 SELECT @null_name = NULL /* ** Treat anonymous virtual subscription as DSN subscriber. ** This will cause sp_MSarticletextcol being called in sp_changesubstatus */ DECLARE hCsubstatus CURSOR LOCAL SCROLL_LOCKS FOR SELECT sub.artid, art.objid, sub.srvid, @null_name, /* subscriber name. NULL for virtual */ sub.dest_db, sub.status, case when pub.allow_anonymous = 1 then 1 else 0 end, /*indicate dsn or not */ pub.repl_freq, art.type, pub.immediate_sync, pub.enabled_for_internet, pub.allow_anonymous, sub.subscription_type, sub.sync_type, sub.update_mode, art.name, login_name, sub.loopback_detection FROM syssubscriptions sub, sysarticles art, syspublications pub WHERE pub.name LIKE @publication AND art.name LIKE @article AND sub.srvid = -1 AND sub.artid = art.artid AND art.pubid = pub.pubid SELECT @finished_virtual = 1 END OPEN hCsubstatus FETCH hCsubstatus INTO @artid, @tabid, @srvid, @sub_name, @dest_db, @sub_status, @non_sql_flag, @repl_freq, @art_type, @immediate_sync, @enabled_for_internet, @allow_anonymous, @subscription_type, @sync_type, @update_mode, @art_name, @login_name, @loopback_detection WHILE (@@fetch_status <> -1) BEGIN IF suser_sname(suser_sid()) <> @login_name AND is_srvrolemember('sysadmin') <> 1 AND is_member ('db_owner') <> 1 BEGIN RAISERROR (14126, 11, -1) RETURN (1) END /* ** If current status is same as new status, do nothing. ** @auto_sync_only is used by snapshot for immediate_sync ** publications. */ IF @sub_status = @statusid OR (@from_auto_sync = 1 AND @sync_type <> @automatic) BEGIN FETCH hCsubstatus INTO @artid, @tabid, @srvid, @sub_name, @dest_db, @sub_status, @non_sql_flag, @repl_freq, @art_type, @immediate_sync, @enabled_for_internet, @allow_anonymous, @subscription_type, @sync_type, @update_mode, @art_name, @login_name, @loopback_detection CONTINUE END /* ** Update syssubscription status */ UPDATE syssubscriptions SET status = @statusid FROM syssubscriptions sub, sysarticles art, syspublications pub WHERE pub.name LIKE @publication AND art.artid = @artid AND sub.srvid = @srvid AND sub.artid = @artid AND art.pubid = pub.pubid AND sub.dest_db = @dest_db if @@ERROR <> 0 BEGIN CLOSE hCsubstatus DEALLOCATE hCsubstatus if @@trancount > 0 begin ROLLBACK TRANSACTION changesubstatus commit tran end RAISERROR (14053, 16, -1) RETURN (1) END /* ** Get timestamp of subscription. */ EXEC @retcode = dbo.sp_replincrementlsn @xact_seqno OUTPUT IF @@ERROR <> 0 or @retcode <> 0 BEGIN CLOSE hCsubstatus DEALLOCATE hCsubstatus if @@trancount > 0 begin ROLLBACK TRANSACTION changesubstatus commit tran end RETURN (1) END select @sub_ts = @xact_seqno IF @sub_ts IS NULL BEGIN CLOSE hCsubstatus DEALLOCATE hCsubstatus if @@trancount > 0 begin ROLLBACK TRANSACTION changesubstatus commit tran end RAISERROR (14053, 16, -1) RETURN (1) END /* ** If activating subscription, update sysarticles, sysobjects and ** MSrepl_subscriptions. */ IF @statusid = @active BEGIN /* ** Update status of article to show it has been activated. */ IF @repl_freq = 0 and EXISTS (SELECT * FROM sysarticles WHERE artid = @artid AND status & 1 <> 1) BEGIN UPDATE sysarticles SET status = status | 1 WHERE artid = @artid IF @@ERROR <> 0 BEGIN CLOSE hCsubstatus DEALLOCATE hCsubstatus if @@trancount > 0 begin ROLLBACK TRANSACTION changesubstatus commit tran end RAISERROR (14069, 16, -1) RETURN (1) END SELECT @art_change = 1 END /* ** Turn the replication flag on for this object in the ** sysobjects table (make it logbased). */ if @repl_freq = 0 BEGIN UPDATE sysobjects SET replinfo = replinfo | @replicate_bit WHERE id = ( SELECT objid FROM sysarticles WHERE artid = @artid ) END IF @@ERROR <> 0 BEGIN CLOSE hCsubstatus DEALLOCATE hCsubstatus if @@trancount > 0 begin ROLLBACK TRANSACTION changesubstatus commit tran end RAISERROR (14068, 16, -1) RETURN (1) END END /* ** Update status of all Text\Image columns if ** subscriber is non-SQL Server. */ IF @non_sql_flag <> 0 AND ( @art_type & 1 ) = 1 BEGIN IF @statusid = @subscribed OR @statusid = @active BEGIN EXEC @retcode = dbo.sp_MSarticletextcol @artid, NULL, 'nonsqlsub', 'add' IF @@ERROR <> 0 OR @retcode <> 0 BEGIN CLOSE hCsubstatus DEALLOCATE hCsubstatus if @@trancount > 0 begin ROLLBACK TRANSACTION changesubstatus commit tran end RAISERROR (14068, 16, -1) RETURN (1) END END ELSE IF @statusid = @inactive BEGIN EXEC @retcode = dbo.sp_MSarticletextcol @artid, NULL, 'nonsqlsub', 'drop' IF @@ERROR <> 0 OR @retcode <> 0 BEGIN CLOSE hCsubstatus DEALLOCATE hCsubstatus if @@trancount > 0 begin ROLLBACK TRANSACTION changesubstatus commit tran end RAISERROR (14068, 16, -1) RETURN (1) END END END /* ** If deactivating subscription, update sysarticles, sysobjects and ** MSrepl_subscriptions. */ IF @statusid <> @active AND @sub_status = @active BEGIN /* ** Set the article status to 'inactive' if there are ** no other active subscriptions on it. */ IF NOT EXISTS (SELECT * FROM syssubscriptions WHERE artid = @artid AND status = @active) BEGIN IF EXISTS (SELECT * FROM sysarticles WHERE artid = @artid AND status & 1 = 1) BEGIN UPDATE sysarticles SET status = status & ~1 WHERE artid = @artid IF @@ERROR <> 0 BEGIN CLOSE hCsubstatus DEALLOCATE hCsubstatus if @@trancount > 0 begin ROLLBACK TRANSACTION changesubstatus commit tran end RAISERROR (14069, 16, -1) RETURN (1) END SELECT @art_change = 1 END END /* ** Set the object replication bits to 'inactive' if ** there are no other active subscriptions on the ** table. */ IF NOT EXISTS (SELECT * FROM syssubscriptions WHERE artid IN (SELECT sa.artid FROM sysarticles sa, syspublications sp WHERE sa.objid = @tabid and sa.pubid = sp.pubid and sp.repl_freq = 0) AND status = @active) BEGIN UPDATE sysobjects SET replinfo = replinfo & ~@replicate_bit WHERE id = (SELECT objid FROM sysarticles WHERE artid = @artid ) IF @@ERROR <> 0 BEGIN CLOSE hCsubstatus DEALLOCATE hCsubstatus RAISERROR (14068, 16, -1) if @@trancount > 0 begin ROLLBACK TRANSACTION changesubstatus commit tran end RETURN (1) END END END if @no_distproc = 0 begin /* ** Add the active subscription to the distributor's ** subscriptions table if changing status from @inactive */ IF @sub_status = @inactive -- From inactive to subscribed or active BEGIN DECLARE @null_char sysname SELECT @null_char = NULL DECLARE @zero_bit bit SELECT @zero_bit = 0 SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSadd_subscription' EXEC @retcode = @distproc @@SERVERNAME, @pub_db, @sub_name, @artid, @dest_db, @statusid, @sub_ts, @publication, @null_char, /* Pass null to @article, we already gave @artid */ @subscription_type, --@immediate_sync, @sync_type, @zero_bit, @frequency_type, @frequency_interval, @frequency_relative_interval, @frequency_recurrence_factor, @frequency_subday, @frequency_subday_interval, @active_start_time_of_day, @active_end_time_of_day, @active_start_date, @active_end_date, @optional_command_line = @optional_command_line, -- synctran @update_mode = @update_mode, @loopback_detection = @loopback_detection, @distribution_jobid = @distribution_jobid OUTPUT IF @@ERROR <> 0 OR @retcode <> 0 BEGIN CLOSE hCsubstatus DEALLOCATE hCsubstatus RAISERROR (14070, 16, -1) if @@trancount > 0 begin ROLLBACK TRANSACTION changesubstatus commit tran end RETURN (1) END END ELSE -- From subscribed or active to others BEGIN /* ** Drop the deactivated subscription from the distributor's ** subscriptions table. */ IF @statusid = @inactive -- From subscribed to inactive or from active to inactive BEGIN SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSdrop_subscription' EXEC @retcode = @distproc @@SERVERNAME, @pub_db, @sub_name, @artid, @dest_db, @publication IF @@ERROR <> 0 OR @retcode <> 0 BEGIN CLOSE hCsubstatus DEALLOCATE hCsubstatus RAISERROR (14070, 16, -1) if @@trancount > 0 begin ROLLBACK TRANSACTION changesubstatus commit tran end RETURN (1) END END ELSE -- From subscribed to active or from active to subscribed. BEGIN -- Don't do it if activating the subscription for snapshot agent. IF NOT (@from_auto_sync = 1 AND @statusid = @active) BEGIN SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSupdate_subscription' EXEC @retcode = @distproc @@SERVERNAME, @pub_db, @sub_name, @artid, @statusid, @sub_ts, @dest_db IF @@ERROR <> 0 OR @retcode <> 0 BEGIN CLOSE hCsubstatus DEALLOCATE hCsubstatus RAISERROR (14070, 16, -1) if @@trancount > 0 begin ROLLBACK TRANSACTION changesubstatus commit tran end RETURN (1) END END END END end /* ** Set internal object replication bit to 'inactive' if ** there are no other active subscriptions on the ** table. */ IF @statusid = @inactive AND @sub_status = @active AND NOT EXISTS (SELECT * FROM syssubscriptions WHERE artid IN (SELECT artid FROM sysarticles WHERE objid = @tabid) AND status = @active) BEGIN /* ** If it's a procedure execution article, clear proc status bits */ IF (@art_type & 8 ) = 8 BEGIN UPDATE sysobjects SET replinfo = replinfo & ~24 WHERE id = @tabid END END /* Turn on object replication */ ELSE IF @statusid = @active BEGIN IF (@art_type & 24 ) = 24 BEGIN UPDATE sysobjects SET replinfo = replinfo | 24 WHERE id = @tabid END ELSE IF( @art_type & 8 ) = 8 BEGIN UPDATE sysobjects SET replinfo = replinfo | 8 WHERE id = @tabid END END -- updates done flush in-memory object schema info declare @qualified_name nvarchar(512) exec dbo.sp_MSget_qualified_name @tabid, @qualified_name output exec dbo.sp_replupdateschema @qualified_name /* ** Get next row. */ FETCH hCsubstatus INTO @artid, @tabid, @srvid, @sub_name, @dest_db, @sub_status, @non_sql_flag, @repl_freq, @art_type , @immediate_sync, @enabled_for_internet, @allow_anonymous, @subscription_type, @sync_type, @update_mode, @art_name, @login_name, @loopback_detection END -- end while for cursor CLOSE hCsubstatus DEALLOCATE hCsubstatus END -- end while for virtual and real -- force refresh of article cache -- Bug 25265: Only do it if necessary -- Bug 47732: No need on brute force cleanup IF ( @art_change = 1 ) and ( @ignore_distributor = 0 ) EXECUTE dbo.sp_replflush COMMIT TRANSACTION RETURN(0) go EXEC dbo.sp_MS_marksystemobject sp_changesubstatus GO print '' print 'Creating procedure sp_addsubscription' go CREATE PROCEDURE sp_addsubscription ( @publication sysname, /* publication name */ @article sysname = 'all', /* article name */ @subscriber sysname = NULL, /* subscriber name */ @destination_db sysname = NULL, /* destination database */ @sync_type nvarchar (15) = 'automatic', /* subscription sync type */ @status sysname = NULL, /* subscription status */ @subscription_type nvarchar(4) = 'push', /* subscription type: ** 'push' or 'pull' */ -- SyncTran @update_mode nvarchar(15) = 'read only', -- Can be 'read only', 'sync tran' @loopback_detection nvarchar(5) = NULL, -- 'true' or 'false' -- end SyncTran @frequency_type int = NULL, @frequency_interval int = NULL, @frequency_relative_interval int = NULL, @frequency_recurrence_factor int = NULL, @frequency_subday int = NULL, @frequency_subday_interval int = NULL, @active_start_time_of_day int = NULL, @active_end_time_of_day int = NULL, @active_start_date int = NULL, @active_end_date int = NULL, @optional_command_line nvarchar(4000) = NULL, @reserved nvarchar(10) = NULL, /* reserved, used when calling from other system */ /* stored procedures, it will be set to 'internal'.*/ /* It should never be used directly */ @enabled_for_syncmgr nvarchar(5) = 'false' /* Enabled for SYNCMGR: true or false */ ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @artid int DECLARE @pre_creation_cmd tinyint DECLARE @none tinyint DECLARE @automatic tinyint DECLARE @cmd nvarchar(255) DECLARE @cmd2 nvarchar(255) DECLARE @inactive tinyint DECLARE @active tinyint DECLARE @subscribed tinyint DECLARE @manual tinyint DECLARE @pubid int DECLARE @retcode int DECLARE @srvid smallint DECLARE @subscriber_bit smallint DECLARE @sync_typeid tinyint DECLARE @non_sql_flag bit DECLARE @truncate tinyint DECLARE @sync_method tinyint DECLARE @char_bcp tinyint DECLARE @internal nvarchar(10) DECLARE @status_id tinyint DECLARE @virtual_id smallint DECLARE @subscription_type_id int /* 0 push, 1 pull */ DECLARE @immediate_sync bit /* publication type */ DECLARE @count_subs int DECLARE @count_arts int DECLARE @distribution_jobid binary(16) DECLARE @pubstatus tinyint DECLARE @allow_anonymous bit DECLARE @immediate_sync_ready bit declare @loopback_detection_id bit declare @independent_agent_id bit DECLARE @platform_nt binary DECLARE @dsn_dbname sysname -- SyncTran DECLARE @allow_sync_tran_id bit DECLARE @update_mode_id tinyint -- 0 = read only, 1 = sync tran -- end SyncTran /* ** Initializations. */ SELECT @none = 2 /* Const: synchronization type 'none' */ SELECT @automatic = 1 /* Const: synchronization type 'automatic' */ SELECT @manual = 0 /* Const: synchronization type 'manual' */ SELECT @inactive = 0 /* Const: subscription status 'inactive' */ SELECT @subscribed = 1 /* Const: subscription status 'subscribed' */ SELECT @active = 2 /* Const: subscription status 'arctive' */ SELECT @subscriber_bit = 4 /* Const: subscription server status */ SELECT @truncate = 3 /* Const: truncate pre-creation command */ SELECT @char_bcp = 1 /* Const: character bcp sync method */ SELECT @virtual_id = -1 /* Const: virtual subscriber id */ SELECT @internal = 'internal' /* Const: Flag of calling internally from system */ /* stored procedures */ -- Hardcoded in sqlrepl.h SELECT @dsn_dbname = 'DSN' SELECT @platform_nt = 0x1 /* ** Parameter Check: @publication. ** Check to make sure that the publication exists and that it conforms ** to the rules for identifiers. ** set subscription_type for the publication */ IF @publication IS NOT NULL BEGIN EXECUTE @retcode = dbo.sp_validname @publication IF @retcode <> 0 RETURN (1) IF NOT EXISTS (SELECT * FROM syspublications WHERE name = @publication) BEGIN RAISERROR (20026, 11, -1, @publication) RETURN (1) END END /* ** Parameter Check: @subscription_type ** Valid values: ** push ** pull ** */ IF LOWER(@subscription_type) NOT IN ('push', 'pull') BEGIN RAISERROR (14128, 16, -1) RETURN (1) END IF LOWER(@subscription_type) = 'push' SELECT @subscription_type_id = 0 ELSE SELECT @subscription_type_id = 1 /* ** Security Check. */ IF @subscription_type_id = 0 BEGIN exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) END ELSE BEGIN exec @retcode = dbo.sp_MSreplcheck_pull @publication if @@ERROR <> 0 or @retcode <> 0 return(1) END SELECT @pubid = pubid, @sync_method = sync_method, @immediate_sync = immediate_sync, @pubstatus = status, @allow_anonymous = allow_anonymous, @immediate_sync_ready = immediate_sync_ready, -- SyncTran @allow_sync_tran_id = allow_sync_tran, @independent_agent_id = independent_agent FROM syspublications WHERE name = @publication select @srvid = srvid from master..sysservers where UPPER(srvname)=UPPER(@subscriber) if exists (select name from sysobjects where name='sysmergesubscriptions') begin IF exists (select name from sysarticles where pubid=@pubid and objid in (select objid from sysmergearticles where pubid in (select pubid from sysmergesubscriptions where db_name=@destination_db and srvid=@srvid))) begin RAISERROR(20084, 16, -1, @publication, @destination_db) return (1) end end IF @pubid IS NULL BEGIN RAISERROR (14043, 16, -1, '@pubid') RETURN (1) END /* ** Check to see if the desired subscription type is allowed */ /* ** push ** Virtual subscriptions are always push type */ IF @subscription_type_id = 0 AND @subscriber IS NOT NULL BEGIN IF NOT EXISTS (SELECT * from syspublications where allow_push = 1 AND pubid = @pubid) BEGIN RAISERROR (20012, 16, -1, @subscription_type, @publication) RETURN (1) END END /* pull */ IF @subscription_type_id = 1 AND @subscriber IS NOT NULL BEGIN IF NOT EXISTS (SELECT * from syspublications where allow_pull = 1 AND pubid = @pubid) BEGIN RAISERROR (20012, 16, -1, @subscription_type, @publication) RETURN (1) END END /* ** Parameter Check: @subscriber. ** ** Check if the server exists and that it is a subscription server. ** ** @subscriber is NULL represent virtual subscription, which is not allowed ** in following case: ** 1. Non-immediate-sync publication ** 2. the stored procedure is not in the internal usage mode ** (called by system stored procedures) ** 3. non push mode ** */ IF @subscriber IS NULL AND ( @immediate_sync = 0 OR @subscription_type_id <> 0 OR @reserved <> @internal) BEGIN RAISERROR (14043, 16, -1, '@subscriber') RETURN (1) END IF @subscriber IS NULL BEGIN /* set virtual subscriber ID */ SELECT @srvid = @virtual_id select @non_sql_flag = 0 END ELSE BEGIN /* validate name and get subscriber ID and server status */ EXECUTE @retcode = dbo.sp_validname @subscriber IF @retcode <> 0 RETURN (1) select @srvid = null SELECT @srvid = srvid, @non_sql_flag = case when srvproduct = N'MSREPL-NONSQL' then 1 else 0 end FROM master..sysservers WHERE UPPER(srvname) = UPPER(@subscriber) AND (srvstatus & @subscriber_bit) <> 0 IF @srvid IS NULL BEGIN RAISERROR (14010, 16, -1) RETURN (1) END END /* ** Parameter Check: @destination_db. ** @destination_db can not be all. ** Set @destination_db to current database if not specified. Make ** sure that the @destination_db conforms to the rules for identifiers. */ if LOWER(@destination_db) = 'all' BEGIN RAISERROR (14032, 16, -1, '@destination_db') RETURN (1) END IF @destination_db IS NULL SELECT @destination_db = DB_NAME() EXECUTE @retcode = dbo.sp_validname @destination_db IF @retcode <> 0 RETURN (1) /* ** Parameter Check: @article */ /* @article can not be null */ IF @article IS NULL BEGIN RAISERROR (14043, 16, -1, '@article') 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 -- Check if publication allows this option IF @allow_sync_tran_id <> 1 BEGIN RAISERROR (20503, 16, -1, '@update_mode', 'sp_addsubscription') RETURN (1) END END ELSE BEGIN SELECT @update_mode_id = 0 END -- end SyncTran /** For immediate_sync publication, @article has to be 'all' */ IF NOT @reserved = @internal AND @immediate_sync = 1 AND NOT LOWER(@article) = 'all' BEGIN RAISERROR (14122, 16, -1) RETURN (1) END /* For immediate_sync publication,there has to be at least one ** article in the publication before the publication can be subscribed. */ IF @immediate_sync = 1 AND not exists ( SELECT * from sysarticles sa, syspublications sp WHERE sa.pubid = sp.pubid AND sp.name = @publication) BEGIN RAISERROR (14124, 16, -1) RETURN(1) END /* ** For full subscription, check to see if subscriptions ** to ALL the articles exist before expanding parameter @article. ** */ IF LOWER(@article) = 'all' AND @reserved <> @internal AND EXISTS (SELECT * FROM syspublications WHERE pubid = @pubid) BEGIN SELECT @count_arts = count(*) FROM sysarticles art WHERE art.pubid = @pubid SELECT @count_subs = count(*) FROM syssubscriptions sub, sysarticles art WHERE sub.srvid = @srvid AND sub.srvid >= 0 AND sub.dest_db = @destination_db AND sub.artid = art.artid AND art.pubid = @pubid IF (@count_arts = @count_subs) BEGIN RAISERROR (14058, 16, -1) RETURN (1) END END /* ** Real subscription to inactive publicaton is not allowed ** Note, subscriptions to the new article will be added automatically ** for immediate_sync publications. At that time, the publication may not ** be active. */ IF @srvid <> @virtual_id AND @pubstatus = 0 AND @reserved <> @internal BEGIN RAISERROR (21000, 16, -1) RETURN (1) END /* ** Do special things for DSN subscribers. */ IF @subscriber IS NOT NULL AND @non_sql_flag <> 0 BEGIN -- DSN subscriber cannot subscribe to native mode publication IF @sync_method <> @char_bcp BEGIN RAISERROR (14095, 16, -1, @publication, @subscriber) RETURN (1) END -- DSN subscriber cannot subscribe with 'Sync Update' IF @update_mode_id <> 0 BEGIN RAISERROR (21032, 16, -1, @subscriber) RETURN (1) END -- DSN subscriber cannot subscribe to article using custom procs -- or articles using parameterized statements -- ( only run this test during execs when the article name is actually specified ) IF( LOWER( @article ) <> 'all' ) BEGIN --IF EXISTS ( select * from sysarticles sa, syspublications sp --where sa.pubid = sp.pubid --and sp.name = @publication --and sa.name = @article --and ( ins_cmd like '%call%' or upd_cmd like '%call%' or del_cmd like '%call%' ) ) --BEGIN --RAISERROR(21051, 16, -1, @subscriber) --RETURN (1) --END IF EXISTS ( select * from sysarticles sa, syspublications sp where sa.pubid = sp.pubid and sp.name = @publication and sa.name = @article and sa.status & 16 = 16 ) BEGIN RAISERROR(21060, 16, -1, @subscriber) RETURN (1) END END -- bug 24486 subscriber db of DSN subscriber is meaningless -- use internal values IF @non_sql_flag <> 0 SELECT @destination_db = @dsn_dbname END IF LOWER(@article) = 'all' /* ** Get all articles in the publication that are not subscribed to ** by the @subscriber */ BEGIN /* ** Make the operation atomic. This is to prevent multiple subscription_type ** from one subscriber on an immediate_sync publication */ BEGIN TRAN DECLARE hCx CURSOR LOCAL FAST_FORWARD FOR SELECT DISTINCT a.name FROM sysarticles a, syspublications b WHERE a.pubid = b.pubid AND b.name = @publication AND NOT EXISTS (SELECT * from syssubscriptions s WHERE s.artid = a.artid AND s.status <> 0 AND s.srvid = @srvid AND s.dest_db = @destination_db) FOR READ ONLY EXECUTE (@cmd + @cmd2) OPEN hCx FETCH hCx INTO @article WHILE (@@fetch_status <> -1) BEGIN EXECUTE @retcode = dbo.sp_addsubscription @publication = @publication, @article = @article, @subscriber = @subscriber, @destination_db = @destination_db, @sync_type = @sync_type, @status = @status, @subscription_type = @subscription_type, @reserved = @internal, -- SyncTran @update_mode = @update_mode, -- end SyncTran @loopback_detection = @loopback_detection, @frequency_type = @frequency_type, @frequency_interval = @frequency_interval, @frequency_relative_interval = @frequency_relative_interval, @frequency_recurrence_factor = @frequency_recurrence_factor, @frequency_subday = @frequency_subday, @frequency_subday_interval = @frequency_subday_interval, @active_start_time_of_day = @active_start_time_of_day, @active_end_time_of_day = @active_end_time_of_day, @active_start_date = @active_start_date, @active_end_date = @active_end_date, @optional_command_line = @optional_command_line IF @@error <> 0 OR @retcode <> 0 BEGIN CLOSE hCx DEALLOCATE hCx if @@trancount > 0 ROLLBACK TRAN RETURN (1) END FETCH hCx INTO @article END CLOSE hCx DEALLOCATE hCx COMMIT TRAN RETURN (0) END /* After 'all' being expanded, check to make sure that the article exists, ** is not NULL, and conforms to the rules for identifiers. */ /* EXECUTE @retcode = dbo.sp_validname @article IF @retcode <> 0 RETURN (1) */ SELECT @artid = artid, @pre_creation_cmd = pre_creation_cmd FROM sysarticles WHERE name = @article AND pubid = @pubid IF NOT EXISTS (SELECT * FROM sysarticles WHERE artid = @artid AND pubid = @pubid) BEGIN RAISERROR (20027, 11, -1, @article) RETURN (1) END /* ** If the subscriber is an ODBC DSN, do not allow subscriptions to ** articles with a "truncate" pre_creation_cmd. */ IF @non_sql_flag <> 0 AND @pre_creation_cmd = @truncate BEGIN RAISERROR (14094, 16, -1, @article, @subscriber) RETURN (1) END /* ** Parameter Check: @sync_type. ** Set sync_typeid based on the @sync_type specified. ** ** sync_typeid sync_type ** =========== ========= ** 0 manual ** 1 automatic ** 2 none */ IF LOWER(@sync_type) NOT IN ('automatic', 'manual', 'none') BEGIN RAISERROR (14052, 16, -1) RETURN (1) END IF LOWER(@sync_type) = 'manual' BEGIN RAISERROR (14123, 16, -1) RETURN (1) END IF LOWER(@sync_type) = 'automatic' BEGIN SELECT @sync_typeid = @automatic END ELSE BEGIN SELECT @sync_typeid = @none END /* ** Bug 12850: ** Make sure that the creation_script is specified if pre_creation_cmd is "drop" ** Note that at this point, @article cannot be 'all'. */ /* NO LONGER REQUIRED IN 7.0 if exists (select * from sysarticles where name = @article AND pre_creation_cmd = 1 AND creation_script is null) BEGIN RAISERROR (14096, 16, -1) RETURN (1) END */ /* ** Parameter Check: @status ** If the publication is immediate_sync type and sync_type is automatic ** the status has to be NULL. ** Note for 6x backward compatibility, don't do the check for non immediate_sync ** publication */ IF @immediate_sync = 1 and @sync_typeid = @automatic AND @status IS NOT NULL BEGIN RAISERROR (14129, 16, -1) RETURN (1) END /* ** Parameter Check: @loopback_detection */ IF @loopback_detection is not null and LOWER(@loopback_detection) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@loopback_detection') RETURN (1) END IF LOWER(@loopback_detection) = 'true' SELECT @loopback_detection_id = 1 ELSE IF LOWER(@loopback_detection) = 'false' SELECT @loopback_detection_id = 0 ELSE -- if @loopback_detection is null, we will chose the value begin if @update_mode_id = 1 begin declare @tabid int select @tabid = objid from sysarticles where artid = @artid -- Determine if table has timestamp property if ObjectProperty(@tabid, 'TableHasTimestamp') = 1 begin exec @retcode = dbo.sp_MSis_col_replicated @publication, @article, 'timestamp' if @@error <> 0 return (1) if @retcode = 1 select @loopback_detection_id = 1 else select @loopback_detection_id = 0 end else select @loopback_detection_id = 0 end else select @loopback_detection_id = 0 end /* ** Add subscription to syssubscriptions */ begin tran save TRAN addsubscription /* ** If no subscription exists, add it to syssubscriptions. */ /* (leih) SID: getting around bug( 17371 ) */ IF NOT EXISTS (SELECT * FROM syssubscriptions WHERE srvid = @srvid AND artid = @artid AND dest_db = @destination_db) BEGIN INSERT syssubscriptions (artid, srvid, dest_db, login_name, status, sync_type, subscription_type, distribution_jobid, -- SyncTran update_mode, loopback_detection) /* timestamp) */ VALUES (@artid, @srvid, @destination_db, suser_sname(suser_sid()), @inactive, @sync_typeid, @subscription_type_id, 0, -- SyncTran @update_mode_id, @loopback_detection_id) /* NULL) */ IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN addsubscription commit tran end RAISERROR (14057, 16, -1) RETURN (1) END END ELSE BEGIN RAISERROR (14058, 16, -1) if @@trancount > 0 begin ROLLBACK TRAN addsubscription commit tran end RETURN (1) END /* ** If the @status was not provided determine the default value. ** If the @sync_type = 'none' then the subscription defaults to 'active'. ** Else the subscription defaults to 'subscribed'. */ IF @status IS NULL BEGIN IF @sync_typeid = @none SELECT @status = 'active' ELSE SELECT @status = 'subscribed' END /* ** Set publication subscription status. */ EXEC @retcode = dbo.sp_changesubstatus @publication = @publication, @article = @article, @subscriber = @subscriber, @status = @status, @destination_db = @destination_db, @frequency_type = @frequency_type, @frequency_interval = @frequency_interval, @frequency_relative_interval = @frequency_relative_interval, @frequency_recurrence_factor = @frequency_recurrence_factor, @frequency_subday = @frequency_subday, @frequency_subday_interval = @frequency_subday_interval, @active_start_time_of_day = @active_start_time_of_day, @active_end_time_of_day = @active_end_time_of_day, @active_start_date = @active_start_date, @active_end_date = @active_end_date, @optional_command_line = @optional_command_line, @distribution_jobid = @distribution_jobid OUTPUT IF @@error <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN addsubscription commit tran end RAISERROR (14057, 16, -1) RETURN (1) END UPDATE syssubscriptions SET distribution_jobid = @distribution_jobid where artid = @artid AND srvid = @srvid AND dest_db = @destination_db IF @@error <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN addsubscription commit tran end RETURN (1) END /* ** If possible, activate the real subscriptions on immediate_sync publication ** immediately. Also, activate the virtual subscriptions on ** anonymous publications immediately. ** We change the subscription status from 'subscribed' to 'active' so that ** sp_MSupdate_subscription will be called, which will set the subscription's ** xactid_ts to the snapshot xactid_ts of virtual subscriptions. This means that ** we have to call sp_changesubstatus again here. We can not combine two calls ** into ONE !!! ** ** Activate the subscription immediately if ** 1. The publication is immediate_sync type ** 2. sync_type is 'automatic' ** AND ** 1. The subscription is real ** 2. The snapshot has completed once ** 3. The subscription is the last subscription added to the publication (subscription for ** the last article). This is to guarantee the subscription status of all the articles ** in the publication be activate in one transaction at the distributor. This is ** to prevent the distribution agent from picking up partial subscriptions. ** Note that this SP will be called with @article = 'all' ** OR ** 1. The publication is active ** 2. The publication is allow_anonymous ** 3. The subscription is virtual ** */ IF @sync_typeid = @automatic AND @immediate_sync = 1 AND ((@srvid <> @virtual_id AND @immediate_sync_ready = 1 AND NOT EXISTS (select * from sysarticles art where art.pubid = @pubid and not exists (select * from syssubscriptions sub where sub.artid = art.artid and sub.srvid = @srvid and sub.dest_db = @destination_db))) OR (@pubstatus = 1 and @srvid = @virtual_id and @allow_anonymous = 1)) BEGIN DECLARE @article_ex sysname IF @srvid <> @virtual_id SELECT @article_ex = '%' ELSE SELECT @article_ex = @article /* ** Set publication subscription status. */ EXEC @retcode = dbo.sp_changesubstatus @publication = @publication, @article = @article_ex, @subscriber = @subscriber, @status = 'active', @destination_db = @destination_db IF @@error <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN addsubscription commit tran end RAISERROR (14057, 16, -1) RETURN (1) END END /* Conditional support for MobileSync */ if LOWER(@enabled_for_syncmgr) = 'true' BEGIN /* MobileSync Support */ declare @distributor_server sysname declare @distributor_security_mode int declare @distributor_login sysname declare @distributor_password sysname declare @publisher_db sysname set @publisher_db = DB_NAME() /* ** The registry entry needs to be created only for push subscriptions - ** i.e - need not be called when a pull subscription is created at the ** subscriber and sp_addmergesubscription is being called then. */ IF LOWER(@subscription_type) = 'push' BEGIN EXECUTE @retcode = dbo.sp_helpdistributor @distributor = @distributor_server OUTPUT /* Distributor RPC server name */ IF @@ERROR <> 0 or @retcode <> 0 BEGIN if @@trancount > 0 ROLLBACK TRAN addsubscription RAISERROR (14057, 16, -1) RETURN (1) END -- Always use integrated security on winNT if (@platform_nt = platform() & @platform_nt ) begin set @distributor_security_mode = 1 end -- For Win9x the dist publisher and distributor are the same machine else begin select @distributor_security_mode = 0, @distributor_login = login, @distributor_password = password from msdb..MSdistpublishers where UPPER(name) = UPPER(@@servername) end /* Call sp_MSregistersubscription so that the subscription can be synchronized via Onestop etc. */ declare @subscription_id uniqueidentifier set @subscription_id = convert(uniqueidentifier, @distribution_jobid) exec @retcode = dbo.sp_MSregistersubscription @replication_type = 1, @publisher = @@SERVERNAME, @publisher_db = @publisher_db, @publication = @publication, @subscriber = @subscriber, @subscriber_db = @destination_db, @distributor = @distributor_server, @distributor_security_mode = @distributor_security_mode, @distributor_login = @distributor_login, @distributor_password = @distributor_password, @subscription_id = @subscription_id, @independent_agent = @independent_agent_id, @subscription_type = @subscription_type_id IF @@ERROR <> 0 or @retcode <> 0 BEGIN if @@trancount > 0 ROLLBACK TRAN addsubscription RAISERROR (14057, 16, -1) RETURN (1) END END END COMMIT TRAN go EXEC dbo.sp_MS_marksystemobject sp_addsubscription GO print '' print 'Creating procedure sp_changearticle' GO CREATE PROCEDURE sp_changearticle ( @publication sysname = NULL, /* Publication name */ @article sysname = NULL, /* Article name */ @property nvarchar(20) = NULL, /* The property to change */ @value nvarchar(255) = NULL /* The new property value */ ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @artid int DECLARE @cmd1 nvarchar(512) DECLARE @cmd2 nvarchar(512) DECLARE @db sysname DECLARE @filter int DECLARE @object sysname DECLARE @owner sysname DECLARE @pubid int DECLARE @retcode int DECLARE @site sysname DECLARE @sync_objid int DECLARE @typeid tinyint DECLARE @precmdid tinyint DECLARE @active tinyint DECLARE @virtual_id smallint DECLARE @objid int DECLARE @objtype nchar(2) DECLARE @old_filter_name sysname DECLARE @distributor sysname DECLARE @distribdb sysname DECLARE @dbname sysname DECLARE @distproc nvarchar (255) DECLARE @article_id int select @active = 2 select @virtual_id = -1 /* ** Security Check */ exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Check to see if the database has been activated for publication. */ IF (SELECT category & 1 FROM master..sysdatabases WHERE name = DB_NAME()) = 0 BEGIN RAISERROR (14013, 16, -1) RETURN (1) END /* ** Parameter Check: @publication. ** Make sure that the publication exists. */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) SELECT @pubid = pubid FROM syspublications WHERE name = @publication IF @pubid IS NULL BEGIN RAISERROR (20026, 11, -1, @publication) RETURN (1) END ELSE /* ** Check to see that the article exists in sysarticles. ** Fetch the article identification number. */ IF @article IS NULL BEGIN RAISERROR (14043, 16, -1, '@article') RETURN (1) END /* EXECUTE @retcode = dbo.sp_validname @article IF @retcode <> 0 RETURN (1) */ SELECT @artid = artid FROM sysarticles WHERE name = @article AND pubid = @pubid IF @artid IS NULL BEGIN RAISERROR (20027, 11, -1, @article) RETURN (1) END /* ** Some options on cannot be modified if articles have active subscriptions ** (excluding virtual subscriptions). */ IF EXISTS (SELECT * FROM syssubscriptions WHERE artid = @artid AND status = @active AND srvid >=0 AND @property in (N'type', N'filter') ) BEGIN RAISERROR (14092, 11, -1, @property, @article ) RETURN (1) END /* ** Get the object id and type from sysobjects */ SELECT @objtype = type FROM sysobjects WHERE id = ( SELECT objid FROM sysarticles WHERE artid = @artid AND pubid = @pubid ) IF @objtype IS NULL BEGIN RAISERROR( 20027, 11, -1, @article ) 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 ('description') INSERT INTO #tab1 VALUES ('sync_object') INSERT INTO #tab1 VALUES ('type') INSERT INTO #tab1 VALUES ('ins_cmd') INSERT INTO #tab1 VALUES ('del_cmd') INSERT INTO #tab1 VALUES ('upd_cmd') INSERT INTO #tab1 VALUES ('filter') INSERT INTO #tab1 VALUES ('dest_table') INSERT INTO #tab1 VALUES ('dest_object') INSERT INTO #tab1 VALUES ('creation_script') INSERT INTO #tab1 VALUES ('pre_creation_cmd') INSERT INTO #tab1 VALUES ('status') INSERT INTO #tab1 VALUES ('schema_option') INSERT INTO #tab1 VALUES ('destination_owner') PRINT '' SELECT * FROM #tab1 RETURN (0) END IF @objtype = 'U' AND LOWER(@property) NOT IN ('description', 'sync_object', 'type', 'ins_cmd', 'del_cmd', 'upd_cmd', 'filter', 'dest_table', 'dest_object', 'creation_script', 'pre_creation_cmd', 'status', 'schema_option', 'destination_owner') BEGIN RAISERROR (14022, 16, -1) RETURN (1) END IF @objtype = 'P' AND LOWER(@property) NOT IN ('description', 'dest_object', 'dest_table', 'creation_script', 'pre_creation_cmd', 'schema_option', 'destination_owner') BEGIN RAISERROR ( 14110, 16, -1 ) RETURN (1) END /* dest_object and 'dest_table' are same */ IF LOWER(@property) = 'dest_object' SELECT @property = 'dest_table' /* ** Change the property. */ begin tran save TRAN sp_changearticle IF LOWER(@property) IN ( 'description', 'ins_cmd', 'del_cmd', 'upd_cmd', 'dest_table', 'creation_script', 'dest_object') BEGIN /* ** Check the validity of the destination object. NULL should ** get converted to the source object name. Destination object ** names can be owner qualified, but not database qualified. */ IF LOWER(@property) = 'dest_table' OR LOWER(@property) = 'dest_object' BEGIN IF @value IS NULL SELECT @value = object_name(objid) FROM sysarticles WHERE artid = @artid AND pubid = @pubid END SELECT @cmd1 = 'UPDATE sysarticles ' IF @value IS NULL BEGIN SELECT @cmd1 = @cmd1 + ' SET ' + LOWER(@property) + ' = NULL' SELECT @cmd2 = ' WHERE artid = ' + STR(@artid) SELECT @cmd2 = @cmd2 + ' AND pubid = ' + STR(@pubid) EXECUTE (@cmd1 + @cmd2) END ELSE BEGIN SELECT @cmd1 = @cmd1 + ' SET ' + LOWER(@property) + ' = ''' + @value + '''' SELECT @cmd2 = ' WHERE artid = ' + STR(@artid) SELECT @cmd2 = @cmd2 + ' AND pubid = ' + STR(@pubid) EXECUTE (@cmd1 + @cmd2) END IF LOWER(@property) = 'upd_cmd' BEGIN IF ( 0 <> ( SELECT PATINDEX( '%[789].[0-9]%', @@version ) ) ) OR ( 0 <> ( SELECT PATINDEX( '%[1-9][0-9].[0-9]%', @@version ) ) ) BEGIN SELECT @objid = objid FROM sysarticles WHERE artid = @artid AND pubid = @pubid exec dbo.sp_MSsetfilteredstatus @objid END END IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END END IF LOWER(@property) = 'sync_object' BEGIN /* ** Check for a valid synchronization object. */ IF @value IS NULL BEGIN RAISERROR (14043, 16, -1, '@value') if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END IF @value LIKE '%.%.%' OR @value LIKE '%.%' BEGIN select @object = PARSENAME( @value, 1 ) select @owner = PARSENAME( @value, 2 ) select @db = PARSENAME( @value, 3 ) select @site = PARSENAME( @value, 4 ) if @object IS NULL return 1 END SELECT @sync_objid = OBJECT_ID(@value) IF @sync_objid IS NULL BEGIN RAISERROR (15001, 11, -1, @value) if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END IF NOT EXISTS (SELECT * FROM sysobjects WHERE type IN ('U', 'V') AND id = @sync_objid) BEGIN RAISERROR (14031, 16, -1) if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END /* ** Update the article with the new synchronization object. */ UPDATE sysarticles SET sync_objid = @sync_objid WHERE artid = @artid AND pubid = @pubid IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END END IF LOWER(@property) = 'type' BEGIN /* ** Check to make sure that we have a valid type. */ IF LOWER(@value) NOT IN ('logbased', 'logbased manualfilter', 'logbased manualview', 'logbased manualboth') BEGIN RAISERROR (14023, 16, -1) if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END /* ** Determine the integer value for the type. */ IF LOWER(@value) = 'logbased' SELECT @typeid = 1 ELSE IF LOWER(@value) = 'logbased manualfilter' SELECT @typeid = 3 ELSE IF LOWER(@value) = 'logbased manualview' SELECT @typeid = 5 ELSE IF LOWER(@value) = 'logbased manualboth' SELECT @typeid = 7 /* ** Update the article with the new type. */ UPDATE sysarticles SET type = @typeid WHERE artid = @artid AND pubid = @pubid IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END END IF LOWER(@property) = 'filter' BEGIN /* ** Check for a valid filter value. */ IF @value IS NOT NULL BEGIN IF @value LIKE '%.%.%' OR @value LIKE '%.%' BEGIN select @object = PARSENAME( @value, 1 ) select @owner = PARSENAME( @value, 2 ) select @db = PARSENAME( @value, 3 ) select @site = PARSENAME( @value, 4 ) if @object IS NULL return 1 END END SELECT @filter = OBJECT_ID(@value) IF @value IS NOT NULL BEGIN IF @filter IS NULL BEGIN RAISERROR (15001, 11, -1, @value) if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END IF NOT EXISTS (SELECT * FROM sysobjects WHERE type = 'RF' AND id = @filter) BEGIN RAISERROR (14049, 16, -1) if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END END IF @value IS NULL SELECT @filter = 0 ----------------------------- -- save off the old filter ----------------------------- SELECT @old_filter_name = object_name( filter ) FROM sysarticles WHERE artid = @artid AND pubid = @pubid IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END -------------------------------------------- -- Update the article with the new filter. -------------------------------------------- UPDATE sysarticles SET filter = @filter WHERE artid = @artid AND pubid = @pubid IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END -- SQL SERVER > 7.x ONLY disassociate old filter with table -- and associate new one IF ( 0 <> ( SELECT PATINDEX( '%[789].[0-9]%', @@version ) ) ) OR ( 0 <> ( SELECT PATINDEX( '%[1-9][0-9].[0-9]%', @@version ) ) ) BEGIN ------------------------------------------ -- disassociate table from old filter proc ------------------------------------------ EXEC dbo.sp_MSsetfilterparent @old_filter_name, 0 IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END ------------------------------------ -- get the table id from sysarticles ------------------------------------ SELECT @objid = objid FROM sysarticles WHERE artid = @artid AND pubid = @pubid IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END ------------------------------------------------------ -- set the parent of the filter proc to this object_id ------------------------------------------------------ EXEC dbo.sp_MSsetfilterparent @value, @objid IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END END END IF LOWER(@property) = 'pre_creation_cmd' BEGIN /* ** Check to make sure that we have a valid pre_creation_cmd. */ IF @objtype = 'P' and LOWER(@value) NOT IN ('none', 'drop') BEGIN RAISERROR ( 14111, 16, -1 ) if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END IF LOWER(@value) NOT IN ('none', 'drop', 'delete', 'truncate') BEGIN RAISERROR (14061, 16, -1) if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END /* ** Determine the integer value for the type. */ IF LOWER(@value) = 'none' SELECT @precmdid = 0 ELSE IF LOWER(@value) = 'drop' SELECT @precmdid = 1 ELSE IF LOWER(@value) = 'delete' SELECT @precmdid = 2 ELSE IF LOWER(@value) = 'truncate' SELECT @precmdid = 3 /* ** Update the article with the new pre_creation_cmd. */ UPDATE sysarticles SET pre_creation_cmd = @precmdid WHERE artid = @artid AND pubid = @pubid IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END END IF LOWER(@property) = 'status' BEGIN /* ** Check to make sure that we have a valid type. */ IF LOWER(@value) IN ('not owner qualified', 'owner qualified') BEGIN RAISERROR (21023, 16, -1,@value) if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END IF LOWER(@value) NOT IN ('no column names', 'include column names', 'string literals', 'parameters' ) BEGIN RAISERROR (14097, 16, -1) if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END /* ** Determine the integer value for the type. */ IF LOWER(@value) = 'not owner qualified' UPDATE sysarticles SET status = status & ~4 WHERE artid = @artid AND pubid = @pubid ELSE IF LOWER(@value) = 'owner qualified' UPDATE sysarticles SET status = status | 4 WHERE artid = @artid AND pubid = @pubid ELSE IF LOWER(@value) = 'no column names' UPDATE sysarticles SET status = status & ~8 WHERE artid = @artid AND pubid = @pubid ELSE IF LOWER(@value) = 'include column names' UPDATE sysarticles SET status = status | 8 WHERE artid = @artid AND pubid = @pubid ELSE IF LOWER(@value) = 'string literals' UPDATE sysarticles SET status = status & ~16 WHERE artid = @artid AND pubid = @pubid ELSE IF LOWER(@value) = 'parameters' UPDATE sysarticles SET status = status | 16 WHERE artid = @artid AND pubid = @pubid IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END END IF LOWER(@property) = 'schema_option' BEGIN IF @value IS NULL BEGIN RAISERROR(14146, 16,1) if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END CREATE TABLE #tab_changearticle (value binary(8) NULL) IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END EXEC ('insert #tab_changearticle values (' + @value +')' ) IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END IF @objtype = 'P' AND EXISTS (SELECT * from #tab_changearticle WHERE value <> 0x0000000000000000 AND value <> 0x0000000000000001 ) BEGIN RAISERROR ( 20014, 16, -1 ) if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END UPDATE sysarticles SET schema_option = tab.value from #tab_changearticle tab WHERE artid = @artid AND pubid = @pubid DROP TABLE #tab_changearticle IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END END IF LOWER(@property) = 'destination_owner' BEGIN IF @value IS NOT NULL BEGIN /* ** The destination_owner must conform to the rules ** for identifiers. */ EXECUTE @retcode = dbo.sp_validname @value IF @retcode <> 0 RETURN (1) END UPDATE sysarticles SET dest_owner = @value from sysarticles WHERE artid = @artid AND pubid = @pubid IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END END ------------------------------------------------------------------------- -- some info on articles is also stored at the distributor. -- update info at distributor if these properties change ------------------------------------------------------------------------- if @property in ( N'description', N'dest_table', N'dest_object' ) BEGIN /* ** Get distribution server information for remote RPC call. */ EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distribdb OUTPUT IF @@ERROR <> 0 or @retcode <> 0 BEGIN RAISERROR (14071, 16, -1) if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END SELECT @dbname = DB_NAME() SELECT @article_id = artid from sysarticles where name = @article SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + '.dbo.sp_MSchange_article' EXECUTE @retcode = @distproc @publisher = @@SERVERNAME, @publisher_db = @dbname, @publication = @publication, @article = @article, @article_id = @article_id, @property = @property, @value = @value IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN sp_changearticle commit tran end RETURN (1) END END COMMIT TRAN /* ** Force the article cache to be refreshed with the new definition. */ EXECUTE dbo.sp_replflush /* ** Return succeed. */ RAISERROR (14025, 10, -1) RETURN (0) go dump tran master with no_log go EXEC dbo.sp_MS_marksystemobject sp_changearticle GO print '' print 'Creating procedure sp_droparticle' go CREATE PROCEDURE sp_droparticle( @publication sysname, /* The publication name */ @article sysname, /* The article name */ @ignore_distributor bit = 0 ) AS /* ** Declarations. */ DECLARE @cmd nvarchar(255) DECLARE @objid int DECLARE @pubid int DECLARE @publish_bit smallint DECLARE @retcode int DECLARE @filter_name sysname DECLARE @view_name sysname DECLARE @type tinyint DECLARE @procnum smallint DECLARE @virtual_id smallint DECLARE @push tinyint DECLARE @distributor sysname DECLARE @distribdb sysname DECLARE @distproc nvarchar (255) DECLARE @dbname sysname -- SyncTran DECLARE @allow_sync_tran_id bit declare @artid int, @insproc_id int, @updproc_id int, @delproc_id int declare @insproc sysname, @updproc sysname, @delproc sysname declare @filter_id int declare @view_id int SET NOCOUNT ON /* ** Initializations. */ SELECT @virtual_id = -1 /* Const: virtual subscriber id */ SELECT @publish_bit = 1 /* ** Security Check. */ exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Parameter Check: @publication. ** The @publication name must conform to the rules for identifiers. */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @retcode <> 0 RETURN (1) IF NOT EXISTS (SELECT * FROM syspublications WHERE name = @publication) BEGIN RAISERROR (20026, 11, -1, @publication) RETURN (1) END /* ** Get the @pubid. */ -- SyncTran --SELECT @pubid = pubid FROM syspublications WHERE name = @publication SELECT @pubid = pubid, @allow_sync_tran_id = allow_sync_tran FROM syspublications WHERE name = @publication /* ** Parameter Check: @article. ** If the @article is 'all', drop all articles for the specified ** publication (@publication). */ IF LOWER(@article) = 'all' BEGIN DECLARE hC CURSOR LOCAL FAST_FORWARD FOR SELECT DISTINCT name FROM sysarticles WHERE pubid = @pubid OPEN hC FETCH hC INTO @article WHILE (@@fetch_status <> -1) BEGIN EXECUTE dbo.sp_droparticle @publication = @publication, @article = @article, @ignore_distributor = @ignore_distributor FETCH hC INTO @article END CLOSE hC DEALLOCATE hC RETURN (0) END /* ** Parameter Check: @article. ** The @article name must conform to the rules for identifiers. */ IF @article IS NULL BEGIN RAISERROR (14043, 16, -1, '@article') RETURN (1) END /* EXECUTE @retcode = dbo.sp_validname @article IF @retcode <> 0 RETURN (1) */ /* ** Ascertain the existence of the article. */ IF NOT EXISTS (SELECT * FROM sysarticles WHERE name = @article AND pubid = @pubid) BEGIN RAISERROR (20027, 11, -1, @article) RETURN (1) END /* ** Check to make sure that there are no 'real' subscriptions on the article. */ IF EXISTS (SELECT * FROM syssubscriptions, sysarticles WHERE sysarticles.name = @article AND sysarticles.pubid = @pubid AND sysarticles.artid = syssubscriptions.artid AND syssubscriptions.srvid <> @virtual_id) BEGIN RAISERROR (14046, 16, -1) RETURN (1) END -- SyncTran /* ** If allow_sync_procs option turned on for the publication, retrieve info from sysarticle updates */ if @allow_sync_tran_id = 1 begin select @artid = artid from sysarticles where name = @article and pubid = @pubid select @insproc_id = sync_ins_proc, @updproc_id = sync_upd_proc, @delproc_id = sync_del_proc from sysarticleupdates where artid = @artid and pubid = @pubid end -- end SyncTran /* ** Retrieve the object id of the underlying table. */ SELECT @objid = objid, @type = type FROM sysarticles WHERE name = @article AND pubid = @pubid begin tran save TRAN droparticle /* Drop virtual subscription first for @immediate_sync publications */ if EXISTS (SELECT * FROM syspublications WHERE name = @publication AND immediate_sync = 1) BEGIN EXECUTE @retcode = dbo.sp_dropsubscription @publication = @publication, @article = @article, @subscriber = NULL, @ignore_distributor = @ignore_distributor, @reserved = 'internal' IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN droparticle commit tran end RETURN (1) END END /* Drop article at the distributor side */ /* ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC. */ if @ignore_distributor = 0 begin /* ** Get distribution server information for remote RPC call. */ EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distribdb OUTPUT IF @@ERROR <> 0 or @retcode <> 0 BEGIN RETURN (1) END SELECT @dbname = DB_NAME() SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + '.dbo.sp_MSdrop_article' EXECUTE @retcode = @distproc @publisher = @@SERVERNAME, @publisher_db = @dbname, @publication = @publication, @article = @article IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 ROLLBACK TRAN RETURN (1) END end /* ** Delete article from sysarticles and clear publish bit in ** sysobjects. */ /* ** If this article is the only one that references this object, ** then we can safely turn off the publish bit in sysobjects. */ IF NOT EXISTS (SELECT * FROM sysarticles WHERE objid = @objid AND NOT (name = @article AND pubid = @pubid)) BEGIN UPDATE sysobjects SET replinfo = replinfo & ~ @publish_bit WHERE id = (SELECT objid FROM sysarticles WHERE name = @article AND pubid = @pubid) /* EXEC (@cmd) IF @@ERROR <> 0 BEGIN if @@trancount > 0 ROLLBACK TRAN RAISERROR (14047, 16, -1, @article) RETURN (1) END */ END /* ** Drop article view if not logbased manualview (type = 5) */ IF (@type & 5) = 1 BEGIN SELECT @view_id = sysobjects.id FROM sysarticles, sysobjects WHERE sysarticles.name = @article AND pubid = @pubid AND sync_objid = sysobjects.id AND sysobjects.type = 'V' exec sp_MSget_qualified_name @view_id, @view_name OUTPUT END /* ** Drop article filter if not logbased manualfilter (type = 3) */ IF (@type & 3) = 1 BEGIN SELECT @filter_id = sysobjects.id FROM sysarticles, sysobjects WHERE sysarticles.name = @article AND pubid = @pubid AND filter = sysobjects.id AND sysobjects.type = 'RF' exec sp_MSget_qualified_name @filter_id, @filter_name OUTPUT END IF( @type & 3 ) = 3 BEGIN select @filter_id = filter from sysarticles where name = @article and pubid = @pubid exec sp_MSget_qualified_name @filter_id, @filter_name OUTPUT if @filter_name is not null EXEC dbo.sp_MSsetfilterparent @filter_name, 0 -- Clear base table dependency on the filter EXEC dbo.sp_MSsetfilteredstatus @objid -- This is a manual filter, we should not drop it automatically -- since it is not created by us. -- Set @filter_id to null so the object will not be dropped later. select @filter_name = null END /* ** If this is a table based article, Drop all article columns. ** This is done to force all Text\Image column status to be updated. */ IF (@type & 8) != 8 BEGIN -- propagate @ignore_distributor to sp_articlecolumn to allow forced cleanup EXECUTE @retcode = dbo.sp_articlecolumn @publication, @article, @operation = 'drop', @ignore_distributor = @ignore_distributor -- synctran , @refresh_synctran_procs = 0 IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRAN droparticle commit tran end RETURN (1) END END /* ** Remove the row from sysarticles. */ DELETE FROM sysarticles WHERE name = @article AND pubid = @pubid IF @@ERROR <> 0 BEGIN if @@trancount > 0 ROLLBACK TRAN RAISERROR (14047, 16, -1, @article) RETURN (1) END -- SyncTran /* ** Drop associated sync tran procs and entries in sysarticle updates */ if @allow_sync_tran_id = 1 begin exec @retcode = dbo.sp_MSdrop_object @object_id = @insproc_id if @retcode <> 0 or @@error <> 0 goto UNDO exec @retcode = dbo.sp_MSdrop_object @object_id = @updproc_id if @retcode <> 0 or @@error <> 0 goto UNDO exec @retcode = dbo.sp_MSdrop_object @object_id = @delproc_id if @retcode <> 0 or @@error <> 0 goto UNDO delete from sysarticleupdates where artid = @artid and pubid = @pubid if @@ERROR <> 0 begin if @@trancount > 0 ROLLBACK TRAN RETURN (1) end end -- end SyncTran COMMIT TRAN IF @view_name IS NOT NULL BEGIN -- @view_name is already quoted. SELECT @cmd = 'drop view ' + @view_name exec (@cmd) END IF @filter_name IS NOT NULL BEGIN -- @filter_name is already quoted. SELECT @cmd = 'drop proc ' + @filter_name exec (@cmd) END /* ** Force the article cache to be refreshed; only if needed */ if ( @ignore_distributor = 0 ) EXECUTE dbo.sp_replflush return (0) UNDO: if @@trancount <> 0 rollback tran go EXEC dbo.sp_MS_marksystemobject sp_droparticle GO print '' print 'Creating procedure sp_droppublication' go CREATE PROCEDURE sp_droppublication( @publication sysname, /* The publication name */ @ignore_distributor bit = 0 ) AS /* ** Declarations. */ DECLARE @article sysname DECLARE @cmd nvarchar(255) DECLARE @retcode int DECLARE @distributor sysname DECLARE @distribdb sysname DECLARE @distproc nvarchar (255) DECLARE @agentname nvarchar (40) DECLARE @dbname sysname DECLARE @virtual_id smallint SELECT @virtual_id = -1 select @dbname = db_name() /* ** Security check */ exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Parameter Check: @publication. ** If the @publication is 'all', drop all publications. Otherwise, ** make sure the @publication is a valid non-null identifier. ** Delete the logreader agent after all the publications have been ** removed. */ IF LOWER(@publication) = 'all' BEGIN DECLARE hC1 CURSOR LOCAL FAST_FORWARD FOR SELECT DISTINCT name FROM syspublications WHERE pubid NOT IN (SELECT pubid FROM sysarticles WHERE artid IN (SELECT artid FROM syssubscriptions WHERE srvid <> @virtual_id)) OPEN hC1 FETCH hC1 INTO @publication WHILE (@@fetch_status <> -1) BEGIN EXECUTE dbo.sp_droppublication @publication, @ignore_distributor = @ignore_distributor FETCH hC1 INTO @publication END CLOSE hC1 DEALLOCATE hC1 RETURN (0) END IF @publication IS NULL BEGIN RAISERROR (14003, 16, -1) RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @retcode <> 0 RETURN (1) /* ** Ascertain the existence of the publication and get the taskid. */ IF NOT EXISTS (SELECT * FROM syspublications WHERE name = @publication) BEGIN RAISERROR (20026, 11, -1, @publication) RETURN (1) END /* ** Check to make sure that there are no subscriptions on the publication. */ IF EXISTS (SELECT * FROM syssubscriptions a, sysarticles b, syspublications c WHERE c.name = @publication AND c.pubid = b.pubid AND b.artid = a.artid AND a.srvid <>@virtual_id) BEGIN RAISERROR (14005, 16, -1) RETURN (1) END /* ** Delete all articles from the publication. */ DECLARE hC2 CURSOR LOCAL FAST_FORWARD FOR SELECT DISTINCT name FROM sysarticles WHERE pubid = (SELECT pubid FROM syspublications WHERE name = @publication) OPEN hC2 FETCH hC2 INTO @article WHILE (@@fetch_status <> -1) BEGIN EXECUTE dbo.sp_droparticle @publication = @publication, @article = @article, @ignore_distributor = @ignore_distributor FETCH hC2 INTO @article END CLOSE hC2 DEALLOCATE hC2 BEGIN TRAN /* ** Delete publication from syspublications. */ DELETE FROM syspublications WHERE name = @publication IF @@ERROR <> 0 GOTO UNDO /* ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC. */ if @ignore_distributor = 0 begin /* ** Get distribution server information for remote RPC call. */ EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distribdb OUTPUT IF @@ERROR <> 0 OR @retcode <> 0 BEGIN RAISERROR (14071, 16, -1) RETURN (1) END /* ** Delete sync agent of Publication if it exists. */ SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + '.dbo.sp_MSdrop_snapshot_agent' EXECUTE @retcode = @distproc @publisher = @@SERVERNAME, @publisher_db = @dbname, @publication = @publication IF @@ERROR <> 0 or @retcode <> 0 GOTO UNDO IF NOT EXISTS (SELECT * FROM syspublications where repl_freq = 0) BEGIN /* ** Delete logreader agent, continue if drop is not successful */ SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + '.dbo.sp_MSdrop_logreader_agent' EXECUTE @retcode = @distproc @publisher = @@SERVERNAME, @publisher_db = @dbname, -- 'ALL' is used in sp_addpublication. @publication = 'ALL' IF @@ERROR <> 0 or @retcode <> 0 GOTO UNDO END /* ** Delete the publication at the distribution server */ SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + '.dbo.sp_MSdrop_publication' EXECUTE @retcode = @distproc @publisher = @@SERVERNAME, @publisher_db = @dbname, @publication = @publication IF @@ERROR <> 0 or @retcode <> 0 GOTO UNDO end COMMIT TRAN return (0) UNDO: if @@TRANCOUNT = 1 ROLLBACK TRAN else COMMIT TRAN return(1) GO EXEC dbo.sp_MS_marksystemobject sp_droppublication GO print '' print 'Creating procedure sp_dropsubscription' go CREATE PROCEDURE sp_dropsubscription ( @publication sysname = NULL, /* The publication name */ @article sysname = NULL, /* The article name */ @subscriber sysname, /* The subscriber name */ @destination_db sysname =NULL, /* Name of the destination database */ /* If null, all the subscriptions from that subscriber will be dropped */ @ignore_distributor bit = 0, @reserved nvarchar(10) = NULL /* reserved, used when calling from other system */ /* stored procedures, it will be set to 'internal'.*/ /* It should never be used directly */ ) AS /* ** Declarations. */ DECLARE @subscriber_bit smallint DECLARE @cmd nvarchar(255) DECLARE @srvid smallint DECLARE @artid int DECLARE @retcode int DECLARE @active tinyint DECLARE @internal nvarchar(10) DECLARE @expand_article nvarchar(10) DECLARE @push tinyint DECLARE @virtual_id smallint DECLARE @login_name sysname DECLARE @immediate_sync bit DECLARE @subscription_type int DECLARE @qualified_subscription_name nvarchar(512) /* ** Initializations. */ SET NOCOUNT ON SELECT @subscriber_bit = 4 /* Const: subscription server status */ SELECT @active = 2 /* Const: subscription status 'active' */ SELECT @push = 0 /* Const: push publication type */ SELECT @virtual_id = -1 /* Const: virtual subscriber id */ SELECT @internal = 'internal' /* Const: Flag of calling internally from system */ /* stored procedures */ SELECT @expand_article = 'expand_art' /* Const: Flag of calling after expand 'all' for @artcle */ /* ** Security Check. ** We use login_name stored in syssubscriptions to manage security */ -- Bug 25691. Test distributor RPC connection before open the cursor /* ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC. */ if @ignore_distributor = 0 begin declare @distributor sysname EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT if @@ERROR <> 0 or @retcode <> 0 return(1) end /* ** If the @subscriber is 'all', the user wants to cancel all subscriptions ** to the specified article(s). */ IF LOWER(@subscriber) = 'all' BEGIN DECLARE hCdrop_subscription1 CURSOR LOCAL FAST_FORWARD FOR SELECT DISTINCT srvname FROM master..sysservers a, syssubscriptions b WHERE srvstatus & @subscriber_bit <> 0 AND a.srvid = b.srvid -- With ANSI Defaults ON, the cursor will automatically -- be closed on commit. Since this proc gets called recursively, -- this can happen. So check before opening. IF CURSOR_STATUS('local','hCdrop_subscription1') = -1 OPEN hCdrop_subscription1 -- Bug : 47836 : must owner qual proc invoke to exec inside server on restore/attach cleanup FETCH hCdrop_subscription1 INTO @subscriber WHILE (@@fetch_status <> -1) BEGIN EXECUTE dbo.sp_dropsubscription @publication = @publication, @article = @article, @subscriber = @subscriber, @destination_db = 'all', @ignore_distributor = @ignore_distributor, @reserved = @reserved IF CURSOR_STATUS('local','hCdrop_subscription1') = -1 OPEN hCdrop_subscription1 FETCH hCdrop_subscription1 INTO @subscriber END CLOSE hCdrop_subscription1 DEALLOCATE hCdrop_subscription1 RETURN (0) END /* ** Parameter Check: @subscriber. ** ** Check if the server exists and that it is a subscription server. ** */ IF @subscriber IS NULL BEGIN SELECT @srvid = @virtual_id END ELSE BEGIN /* validate name and get subscriber ID and server status */ EXECUTE @retcode = dbo.sp_validname @subscriber IF @retcode <> 0 RETURN (1) SELECT @srvid = srvid FROM master..sysservers WHERE UPPER(srvname) = UPPER(@subscriber) AND (srvstatus & @subscriber_bit) <> 0 IF @srvid IS NULL BEGIN RAISERROR (14010, 16, -1) RETURN (1) END END /* ** If the @publication is 'all', the user wants to cancel all subscriptions ** for all publications associated with the specified @subscriber. */ IF LOWER(@publication) = 'all' BEGIN DECLARE hCdrop_subscription2 CURSOR LOCAL FAST_FORWARD FOR SELECT DISTINCT a.name FROM syspublications a, sysarticles b, syssubscriptions c WHERE c.srvid = @srvid AND a.pubid = b.pubid AND b.artid = c.artid OPEN hCdrop_subscription2 FETCH hCdrop_subscription2 INTO @publication WHILE (@@fetch_status <> -1) BEGIN EXECUTE dbo.sp_dropsubscription @publication = @publication, @article = 'all', @subscriber = @subscriber, @destination_db = @destination_db, @ignore_distributor = @ignore_distributor, @reserved = @reserved FETCH hCdrop_subscription2 INTO @publication END CLOSE hCdrop_subscription2 DEALLOCATE hCdrop_subscription2 RETURN (0) END /* ** Parameter Check: @publication. ** Check to make sure that the publication exists and that it conforms ** to the rules for identifiers. */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @retcode <> 0 RETURN (1) IF NOT EXISTS (SELECT * FROM syspublications WHERE name = @publication) BEGIN RAISERROR (20026, 11, -1, @publication) RETURN (1) END /* Get subscription type of the publication */ SELECT @immediate_sync = immediate_sync FROM syspublications WHERE name = @publication /* ** Parameter Check: @article */ /* @article can not be null */ IF @article IS NULL BEGIN RAISERROR (14043, 16, -1, '@article') RETURN (1) END /** For immediate_sync publication, @article has to be 'all' */ -- Relax this constraint since users will need to do this before dropping -- an article /* IF @reserved <> @internal AND @reserved <> @expand_article AND @immediate_sync = 1 AND NOT LOWER(@article) = 'all' BEGIN RAISERROR (14122, 16, -1) RETURN (1) END */ /* ** If the @article is 'all', the user wants to cancel all ** subscriptions on this publisher associated with the given @subscriber ** and @publication. */ IF LOWER(@article) = 'all' BEGIN /* Make the operation automic for immediate_sync publications */ BEGIN TRAN IF @reserved IS NULL SELECT @reserved = @expand_article DECLARE hCdrop_subscription3 CURSOR LOCAL FAST_FORWARD FOR SELECT DISTINCT art.name FROM sysarticles art, syssubscriptions sub, syspublications pub WHERE sub.srvid = @srvid AND sub.artid = art.artid AND art.pubid = pub.pubid AND pub.name = @publication OPEN hCdrop_subscription3 FETCH hCdrop_subscription3 INTO @article WHILE (@@fetch_status <> -1) BEGIN EXECUTE @retcode = dbo.sp_dropsubscription @publication = @publication, @article = @article, @subscriber = @subscriber, @destination_db = @destination_db, @ignore_distributor = @ignore_distributor, @reserved = @reserved IF @@error<>0 OR @retcode <> 0 BEGIN CLOSE hCdrop_subscription3 DEALLOCATE hCdrop_subscription3 GOTO UNDO END FETCH hCdrop_subscription3 INTO @article END CLOSE hCdrop_subscription3 DEALLOCATE hCdrop_subscription3 COMMIT TRAN RETURN (0) END /* ** Parameter Check: @article ** Check if the article exists. */ /* EXECUTE @retcode = dbo.sp_validname @article IF @retcode <> 0 RETURN (1) */ SELECT @artid = artid FROM sysarticles art, syspublications pub WHERE pub.name = @publication AND art.name = @article AND art.pubid = pub.pubid IF @artid IS NULL BEGIN RAISERROR (20027, 11, -1, @article) RETURN (1) END /* ** Parameter Check: @destination_db. ** Set @destination_db to current database if not specified. Make ** sure that the @destination_db conforms to the rules for identifiers. */ IF @destination_db IS NULL BEGIN /* ** Check if the subscription exists. */ IF NOT EXISTS (SELECT * FROM syssubscriptions WHERE srvid = @srvid AND artid = @artid) BEGIN RAISERROR (14055, 11, -1) RETURN (1) END ELSE SELECT @destination_db = 'all' END ELSE BEGIN EXECUTE @retcode = dbo.sp_validname @destination_db IF @retcode <> 0 RETURN (1) END IF LOWER(@destination_db) = 'all' BEGIN DECLARE hCdropsub4 CURSOR LOCAL FAST_FORWARD FOR SELECT DISTINCT dest_db FROM syssubscriptions WHERE srvid = @srvid AND artid = @artid OPEN hCdropsub4 FETCH hCdropsub4 INTO @destination_db WHILE (@@fetch_status <> -1) BEGIN EXECUTE dbo.sp_dropsubscription @publication = @publication, @article = @article, @subscriber = @subscriber, @destination_db = @destination_db, @ignore_distributor = @ignore_distributor, @reserved = @reserved FETCH hCdropsub4 INTO @destination_db END CLOSE hCdropsub4 DEALLOCATE hCdropsub4 RETURN (0) END /* ** Dropping virtual subscriptions is not allowed ** in following case: ** 1. non sa or dbo user ** 2. the stored procedure is not in internal usage mode ** (called by system stored procedures) ** ** Note: Only immediate_sync publications have virtual subscriptions ** */ IF @srvid = @virtual_id AND ( @reserved <> @internal) BEGIN RAISERROR (14056, 16, -1) RETURN (1) END /* ** Check if the subscription exists. */ IF NOT EXISTS (SELECT * FROM syssubscriptions WHERE srvid = @srvid AND artid = @artid AND dest_db = @destination_db) BEGIN RAISERROR (14055, 11, -1) RETURN (1) END /* Check the current login id. It is valid only when ** 1. sa or dbo ** 2. same as the one who add the subscription. */ SELECT @login_name = login_name FROM syssubscriptions WHERE srvid = @srvid AND artid = @artid AND dest_db = @destination_db IF suser_sname(suser_sid()) <> @login_name AND is_srvrolemember('sysadmin') <> 1 AND is_member ('db_owner') <> 1 BEGIN SELECT @qualified_subscription_name = @subscriber + N':' + @destination_db RAISERROR(21120, 11, -1, @qualified_subscription_name, @publication) RETURN (1) END begin tran save TRANSACTION dropsubscription /* If dropping virtual subscriptions, reset immediate_sync_ready bit */ IF @srvid = @virtual_id BEGIN UPDATE syspublications SET immediate_sync_ready = 0 WHERE name = @publication and immediate_sync = 1 and immediate_sync_ready = 1 IF @@ERROR <> 0 goto UNDO END /* ** Change the status of the subscription to 'inactive'. */ EXECUTE @retcode = dbo.sp_changesubstatus @publication = @publication, @article = @article, @subscriber = @subscriber, @status = 'inactive', @destination_db = @destination_db, @ignore_distributor = @ignore_distributor IF @@ERROR <> 0 OR @retcode <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRANSACTION dropsubscription commit tran end RETURN (1) END /* Read the subscription_type befor removing the syssubscriptions row */ select @subscription_type = subscription_type from syssubscriptions WHERE artid = @artid AND srvid = @srvid AND dest_db = @destination_db /* ** Remove subscription from syssubscriptions. */ DELETE syssubscriptions WHERE artid = @artid AND srvid = @srvid AND dest_db = @destination_db IF @@ERROR <> 0 BEGIN if @@trancount > 0 begin ROLLBACK TRANSACTION dropsubscription commit tran end RETURN (1) END /* Call sp_MSunregistersubscription so that the reg entries get deleted (for push subscriptions) */ if @subscription_type = @push begin declare @publisher_db sysname set @publisher_db = DB_NAME() exec @retcode = dbo.sp_MSunregistersubscription @publisher = @@SERVERNAME, @publisher_db = @publisher_db, @publication = @publication, @subscriber = @subscriber, @subscriber_db = @destination_db IF @retcode<>0 or @@ERROR<>0 GOTO UNDO end COMMIT TRANSACTION RETURN (0) UNDO: IF @@TRANCOUNT = 1 ROLLBACK TRAN ELSE COMMIT TRAN RETURN(1) go EXEC dbo.sp_MS_marksystemobject sp_dropsubscription GO print '' print 'Creating procedure sp_subscribe' go CREATE PROCEDURE sp_subscribe ( @publication sysname, /* publication name */ @article sysname = 'all', /* article name */ @destination_db sysname = NULL, /* subscriber database */ @sync_type nvarchar (15) = 'automatic' /* subscription sync type */ ) AS -- New 7.0 sp_addsubscription parameters DECLARE @subscriber sysname DECLARE @status sysname DECLARE @subscription_type nvarchar(4) DECLARE @update_mode nvarchar(15) DECLARE @loopback_detection nvarchar(5) DECLARE @enabled_for_syncmgr nvarchar(5) DECLARE @retcode int SET NOCOUNT ON -- sp_subscribe has to be called from a remote subscriber -- If not, we state that it is unsupported SELECT @subscriber = @@REMSERVER IF @subscriber IS NULL BEGIN RAISERROR (21023, 16, -1,'sp_subscribe') RETURN(1) END SELECT @status = NULL SELECT @subscription_type = 'push' SELECT @update_mode = 'read only' SELECT @loopback_detection = 'false' SELECT @enabled_for_syncmgr = 'false' -- Call sp_addsubscription to do the actual work EXEC @retcode = dbo.sp_addsubscription @publication = @publication, @article = @article, @destination_db = @destination_db, @sync_type = @sync_type, @subscriber = @subscriber, @status = @status, @subscription_type = @subscription_type, @update_mode = @update_mode, @loopback_detection = @loopback_detection, @enabled_for_syncmgr = @enabled_for_syncmgr RETURN @retcode go EXEC dbo.sp_MS_marksystemobject sp_subscribe GO print '' print 'Creating procedure sp_unsubscribe' go CREATE PROCEDURE sp_unsubscribe ( @publication sysname = NULL, /* publication name */ @article sysname = NULL /* article name */ ) AS -- New 7.0 sp_dropsubscription parameters DECLARE @subscriber sysname DECLARE @destination_db sysname DECLARE @retcode int SET NOCOUNT ON -- sp_unsubscribe has to be callled from a remote subscriber -- If not, we state that it is unsupported SELECT @subscriber = @@REMSERVER IF @subscriber IS NULL BEGIN RAISERROR (21023, 16, -1,'sp_unsubscribe') RETURN(1) END -- 6.5 didn't support having multiple databases on the same subscriber -- subscribing to the same publication so here, all subscriptions to the -- same publication will be dropped SELECT @destination_db = NULL -- Call sp_dropsubscription to do the real work EXEC @retcode = sp_dropsubscription @publication = @publication, @article = @article, @subscriber = @subscriber, @destination_db = @destination_db RETURN @retcode go EXEC dbo.sp_MS_marksystemobject sp_unsubscribe GO print '' print 'Creating procedure sp_refreshsubscriptions' go CREATE PROCEDURE sp_refreshsubscriptions ( @publication sysname /* Publication name */ ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @article sysname DECLARE @subscriber sysname DECLARE @dest_db sysname DECLARE @retcode int DECLARE @pubid int DECLARE @immediate_sync bit DECLARE @no_sync tinyint DECLARE @subscription_type_id int DECLARE @subscription_type nvarchar(4) DECLARE @virtual smallint DECLARE @srvid smallint DECLARE @sync_typeid int DECLARE @automatic tinyint DECLARE @sync_type nvarchar(9) SELECT @no_sync = 2 SELECT @virtual = -1 SELECT @automatic = 1 /* ** Security Check */ exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Check to see if the database has been activated for publication. */ IF (SELECT category & 1 FROM master..sysdatabases WHERE name = DB_NAME()) = 0 BEGIN RAISERROR (14013, 16, -1) RETURN (1) END /* ** Parameter Check: @publication. ** Make sure that the publication exists */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) SELECT @pubid = pubid FROM syspublications WHERE name = @publication IF @pubid IS NULL BEGIN RAISERROR (20026, 11, -1, @publication) RETURN (1) END /* Add real subscription to the new articles */ /* Open a cursor on all the pending subscriptions, that is */ /* All the subscriptions on the publication that */ /* are not on an article in the publication. */ /* not including virtual subscriptions */ DECLARE hCrefreshsubscriptions CURSOR LOCAL FAST_FORWARD FOR SELECT DISTINCT art1.name, subs1.dest_db, subs1.srvid FROM syssubscriptions subs1, sysarticles art1 WHERE art1.pubid = @pubid AND subs1.srvid <> @virtual AND EXISTS (SELECT * FROM syssubscriptions subs2, sysarticles art2 WHERE subs2.srvid = subs1.srvid AND subs2.dest_db = subs1.dest_db AND subs2.artid = art2.artid AND art2.pubid = @pubid) AND NOT EXISTS ( SELECT * FROM syssubscriptions subs3 WHERE subs3.artid = art1.artid AND subs3.srvid = subs1.srvid AND subs3.dest_db = subs1.dest_db) FOR READ ONLY OPEN hCrefreshsubscriptions FETCH hCrefreshsubscriptions INTO @article, @dest_db, @srvid WHILE (@@fetch_status <> -1) BEGIN /* ** Get subscription type on the publication */ SELECT @subscription_type_id = subs.subscription_type, @sync_typeid = subs.sync_type from sysarticles art, syssubscriptions subs where art.pubid = @pubid AND subs.srvid = @srvid AND subs.dest_db = @dest_db AND subs.artid = art.artid /* ** only do it if the subscription all have the same subscription type ** and sync_type */ IF NOT EXISTS (SELECT * from sysarticles art, syssubscriptions subs where art.pubid = @pubid AND subs.srvid = @srvid AND subs.dest_db = @dest_db AND subs.artid = art.artid AND (subscription_type <> @subscription_type_id OR sync_type <> @sync_typeid)) BEGIN IF @subscription_type_id = 0 SELECT @subscription_type = 'push' ELSE SELECT @subscription_type = 'pull' if @sync_typeid = @automatic SELECT @sync_type = 'automatic' else SELECT @sync_type = 'none' /* ** Get the server name */ SELECT @subscriber = srvname FROM master.dbo.sysservers WHERE srvid = @srvid EXECUTE @retcode = dbo.sp_addsubscription @publication = @publication, @article = @article, @subscriber = @subscriber, @destination_db = @dest_db, @sync_type = @sync_type, @status = NULL, @subscription_type = @subscription_type, @reserved = 'internal' IF @@ERROR <> 0 OR @retcode <> 0 BEGIN CLOSE hCrefreshsubscriptions DEALLOCATE hCrefreshsubscriptions RETURN (1) END END FETCH hCrefreshsubscriptions INTO @article, @dest_db, @srvid END CLOSE hCrefreshsubscriptions DEALLOCATE hCrefreshsubscriptions GO EXEC dbo.sp_MS_marksystemobject sp_refreshsubscriptions GO print '' print 'Creating procedure sp_MSpublishdb' go CREATE PROCEDURE sp_MSpublishdb( @value sysname, @ignore_distributor bit = 0 ) AS SET NOCOUNT ON /* ** Declarations. */ declare @quoted_db sysname declare @db_name sysname declare @command nvarchar(255) declare @description nvarchar(500) declare @category_name nvarchar(100) DECLARE @agentname nvarchar(300) DECLARE @dbname sysname DECLARE @retcode int DECLARE @distributor sysname DECLARE @distribdb sysname DECLARE @distproc nvarchar (255) DECLARE @replicate_bit smallint SELECT @replicate_bit = 2 /* ** Initialization */ SELECT @dbname = DB_NAME() /* ** Parameter check ** @value */ IF LOWER(@value) NOT IN ('true','false') BEGIN RAISERROR(14137,16,-1) RETURN(1) END /* ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC. */ if @ignore_distributor = 0 begin /* ** Test to see if the distributor is installed and online. */ EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distribdb OUTPUT IF @@ERROR <> 0 or @retcode <> 0 or @distributor IS NULL or @distribdb IS NULL BEGIN IF LOWER(@value) = 'true' RAISERROR (20028, 16, -1) ELSE RAISERROR (20029, 16, -1) RETURN (1) END end /* ** Enable the database for publishing. */ IF LOWER(@value) = 'true' BEGIN /* ** Drop and then create central publish tables */ /* ** Drop first if exists */ EXEC @retcode = dbo.sp_MSdrop_pub_tables IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END /* ** Create central publish tables */ EXEC @retcode = dbo.sp_MScreate_pub_tables IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END END ELSE /* Disable the database for publishing. */ BEGIN /* ** Remove all subscriptions in the database. ** WARNING : must owner qualify proc calls for these to run inside server on restore/attach */ EXEC @retcode = dbo.sp_dropsubscription @publication = 'all', @article = 'all', @subscriber = 'all', @ignore_distributor = @ignore_distributor IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END -- Used for attach and restored db. -- sysservers table in master db might be changed so that -- sp_dropsubscription won't work. Delete the table directly. -- Before dropping the table, we need to unmark repl bits in sysobjects -- see below delete syssubscriptions where srvid >= 0 IF @@ERROR <> 0 BEGIN return (1) END /* ** Remove all publications and articles in the database. */ EXEC @retcode = dbo.sp_droppublication @publication = 'all', @ignore_distributor = @ignore_distributor IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END /* ** Remove all published database transactions from the distribution ** database. */ if @ignore_distributor = 0 begin SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSremove_published_jobs ' EXEC @retcode = @distproc @@SERVERNAME, @dbname IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END end /* ** Publishing shutdown, remove all xacts pending distribution ** If forced cleanup, no need to flush; may need to mark repldone */ if ( @ignore_distributor = 0 ) begin /* ensure we can get in as logreader */ EXEC @retcode = dbo.sp_replflush IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END /* unmark all xacts marked for replication */ select @quoted_db = QUOTENAME(@dbname) EXEC ( 'USE ' + @quoted_db + ' exec dbo.sp_repldone NULL, NULL, 0, 0, 1' ) IF @@ERROR <> 0 BEGIN return (1) END /* release our hold on the db as logreader */ EXEC dbo.sp_replflush IF @@ERROR <> 0 BEGIN RETURN(1) END /* ** Drop central publish tables */ EXEC @retcode = dbo.sp_MSdrop_pub_tables IF @@ERROR <> 0 or @retcode <> 0 BEGIN return (1) END end -- Used for attached and restored db. -- sysservers table in master db might be changed so that -- sp_dropsubscription won't work. Unmark repl bits in sysobjects -- directly. UPDATE sysobjects SET replinfo = replinfo & ~@replicate_bit END return (0) GO EXEC dbo.sp_MS_marksystemobject sp_MSpublishdb GO print '' print 'Creating procedure sp_MSactivate_auto_sub' go CREATE PROCEDURE sp_MSactivate_auto_sub ( @publication sysname, /* Publication name */ @article sysname ) AS SET NOCOUNT ON DECLARE @retcode int /* ** Security Check. */ exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Check to see if the database has been activated for publication. */ IF (SELECT category & 1 FROM master..sysdatabases WHERE name = DB_NAME()) = 0 BEGIN RAISERROR (14013, 16, -1) RETURN (1) END /* ** Parameter Check: @publication. ** Make sure that the publication exists and the publication is not push type */ 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) BEGIN TRAN UPDATE syspublications SET immediate_sync_ready = 1 WHERE name = @publication AND immediate_sync = 1 AND immediate_sync_ready <> 1 IF @@ERROR <> 0 BEGIN GOTO UNDO RETURN (1) END EXECUTE @retcode = dbo.sp_changesubstatus @publication = @publication, @article = @article, @status = 'active', @from_auto_sync = 1 IF @@ERROR <> 0 OR @retcode <> 0 BEGIN GOTO UNDO RETURN (1) END COMMIT TRAN RETURN(0) UNDO: IF @@TRANCOUNT = 1 ROLLBACK TRAN ELSE COMMIT TRAN GO EXEC dbo.sp_MS_marksystemobject sp_MSactivate_auto_sub GO raiserror('Creating procedure sp_MSget_synctran_commands', 0,1) GO CREATE PROCEDURE sp_MSget_synctran_commands( @publication sysname /* publication name */, @article sysname = 'all', @command_only bit = 0 /* 0 if called by snapshot agent, 1 if called by sp_script_..., */ ) AS SET NOCOUNT ON DECLARE @artid int DECLARE @tabid int DECLARE @retcode int declare @art_type tinyint declare @filter_id int declare @filter_clause nvarchar(4000) declare @columns binary(32) DECLARE @pubid int, @art_name sysname, @posted_synctran_artid int, @dest_table sysname, @dest_owner sysname, @proc_owner sysname /* ** Initializations. */ select @posted_synctran_artid = 0 /* ** Security Check. ** We use login_name stored in syssubscriptions to manage security ** Do a relaxed security check here. */ exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) /* ** Parameter Check: @publication ** Check to make sure that the publication exists, that it's not NULL, ** and that it conforms to the rules for identifiers. */ IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) SELECT @pubid = pubid FROM syspublications WHERE name = @publication IF @pubid IS NULL BEGIN RAISERROR (20026, 11, -1, @publication) RETURN (1) END -- If the publication does not allow sync tran return nothing IF NOT EXISTS (SELECT * FROM syspublications WHERE pubid = @pubid and allow_sync_tran = 1) RETURN(0) CREATE TABLE #art_commands (artid int NOT NULL, commands nvarchar(4000) NULL, id int identity NOT NULL) declare @all_article bit if lower(@article) = 'all' select @all_article = 1 else select @all_article = 0 DECLARE hCsynctran_arts CURSOR LOCAL FAST_FORWARD FOR SELECT art.artid, art.objid, art.dest_table, art.dest_owner, art.name, art.type, art.filter, art.columns FROM sysarticles art, syspublications pub WHERE pub.pubid = @pubid and pub.pubid = art.pubid and (art.type & 0x1) = 1 and (art.name = @article or @all_article = 1) FOR READ ONLY OPEN hCsynctran_arts FETCH hCsynctran_arts INTO @artid, @tabid, @dest_table, @dest_owner, @art_name, @art_type, @filter_id, @columns WHILE (@@fetch_status <> -1) BEGIN /* ** Determine conflict detection method */ declare @ts_col sysname -- Determine if table has timestamp property select @ts_col = NULL if ObjectProperty(@tabid, 'TableHasTimestamp') = 1 begin exec dbo.sp_MSis_col_replicated @publication, @art_name, 'timestamp', @ts_col OUTPUT end declare @replcmd nvarchar(4000) declare @insproc sysname, @updproc sysname, @delproc sysname declare @identity_col sysname declare @identity_prop tinyint select @posted_synctran_artid = @artid select @insproc = null, @updproc = null, @delproc = null -- Get sproc names and owner name of the sprocs -- Note artid is unique select @insproc = o.name, @proc_owner = u.name from sysobjects o, sysarticleupdates a, sysusers u where a.artid = @artid and a.sync_ins_proc = o.id and u.uid = o.uid select @updproc = o.name from sysobjects o, sysarticleupdates a where a.artid = @artid and a.sync_upd_proc = o.id select @delproc = o.name from sysobjects o, sysarticleupdates a where a.artid = @artid and a.sync_del_proc = o.id if @insproc IS NULL begin CLOSE hCsynctran_arts DEALLOCATE hCsynctran_arts RAISERROR (14043, 11, -1, '@insproc') RETURN (1) end if @updproc IS NULL begin CLOSE hCsynctran_arts DEALLOCATE hCsynctran_arts RAISERROR (14043, 11, -1, '@updproc') RETURN (1) end if @delproc IS NULL begin CLOSE hCsynctran_arts DEALLOCATE hCsynctran_arts RAISERROR (14043, 11, -1, '@delproc') RETURN (1) end -- Determine if published table has identity col select @identity_col = NULL if ObjectProperty(@tabid, 'TableHasIdentity') = 1 exec @retcode = dbo.sp_MSis_col_replicated @publication, @art_name, 'identity', @identity_col OUTPUT -- Horizontal partition select @filter_clause = 'null' if @filter_id <> 0 begin -- We don't handle manual filters; allow all updates if ((@art_type & 0x3) = 0x3) select @filter_clause = '' else select @filter_clause = RTRIM(LTRIM(CONVERT(nvarchar(4000), filter_clause))) from sysarticles where artid = @artid end declare @fullname nvarchar(512) declare @indkey int declare @indid int declare @key sysname declare @col sysname declare @this_col int declare @src_cols int declare @primary_key_bitmap varbinary(4000) declare @byte varbinary(1) declare @i_byte int declare @num_bytes int declare @i_bit tinyint declare @bitmap_str varchar(8000) declare @bitmap varbinary(4000) -- Get qualified name exec dbo.sp_MSget_qualified_name @tabid, @fullname output -- Get number of columns in the partition. exec dbo.sp_MSget_col_position @tabid, @columns, @key, @col output, @this_col output, 1, -- Get num of columns in the partition. @src_cols output select @num_bytes = @src_cols / 8 + 1 -- Set varbinary length set @byte = 0 set @primary_key_bitmap = @byte set @i_byte = 1 while @i_byte < @num_bytes begin set @primary_key_bitmap = @primary_key_bitmap + @byte set @i_byte = @i_byte + 1 end -- get index id exec @indid = dbo.sp_MStable_has_unique_index @tabid set @indkey = 1 while @indkey < 16 and index_col(@fullname, @indid, @indkey) is not null begin set @key = index_col(@fullname, @indid, @indkey) exec dbo.sp_MSget_col_position @tabid, @columns, @key, @col output, @this_col output set @i_byte = 1 + (@this_col-1) / 8 set @i_bit = power(2, (@this_col-1) % 8 ) set @byte = substring(@primary_key_bitmap, @i_byte, 1 ) set @byte = @byte | @i_bit if @i_byte = 1 begin set @bitmap = @byte end else begin set @bitmap = substring(@primary_key_bitmap, 1, @i_byte - 1) set @bitmap = @bitmap + @byte end if @i_byte <> @num_bytes begin set @primary_key_bitmap = @bitmap + substring(@primary_key_bitmap, @i_byte + 1, @num_bytes - @i_byte) end else set @primary_key_bitmap = @bitmap select @indkey = @indkey + 1 end exec @retcode = master..xp_varbintohexstr @primary_key_bitmap, @bitmap_str output if @retcode <> 0 or @@error <> 0 return 1 if @dest_owner is null begin select @dest_owner = N'null' end select @replcmd = '{call sp_addsynctriggers (N' + quotename(@dest_table,'''') + ', N' + quotename(@dest_owner,'''') + ', N' + quotename(@@SERVERNAME,'''') + ', N' + quotename(db_name(),'''') + ', N' + quotename(@publication,'''') + ', N' + quotename(@insproc,'''') + ', N' + quotename(@updproc,'''') + ', N' + quotename(@delproc,'''') + ', N' + quotename(@proc_owner,'''') + ', N' + ISNULL(quotename(@identity_col,''''),'''null''') + ', N' + ISNULL(quotename(@ts_col,''''), '''null''') + ', N' + quotename(@filter_clause,'''') + ', ' + @bitmap_str + ')}' insert into #art_commands values (@artid, @replcmd) FETCH hCsynctran_arts INTO @artid, @tabid, @dest_table, @dest_owner, @art_name, @art_type, @filter_id, @columns end -- end SyncTran if @command_only = 0 select * from #art_commands order by id else select commands from #art_commands order by id CLOSE hCsynctran_arts DEALLOCATE hCsynctran_arts go EXEC dbo.sp_MS_marksystemobject sp_MSget_synctran_commands GO raiserror('Creating procedure sp_script_synctran_commands', 0,1) GO CREATE PROCEDURE sp_script_synctran_commands( @publication sysname, /* publication name */ @article sysname = 'all' /* article name, all means all article */ ) AS declare @retcode int exec @retcode = dbo.sp_MSget_synctran_commands @publication = @publication, @article = @article, @command_only = 1 if @retcode <> 0 or @@error <> 0 return (1) go dump tran master with no_log go EXEC dbo.sp_MS_marksystemobject sp_script_synctran_commands GO print '' print 'Creating procedure sp_MSaddpub_snapshot' go CREATE PROCEDURE sp_MSaddpub_snapshot ( @publication sysname, @freqtype int = 4 , /* 4== Daily */ @freqinterval int = 1, /* Every day */ @freqsubtype int = 4, /* Sub interval = Minute */ @freqsubinterval int = 5, /* Every five minutes */ @freqrelativeinterval int = 1, @freqrecurrencefactor int = 0, @activestartdate int = 0, /* 12:00 am - 11:59 pm */ @activeenddate int =99991231 , /* No start date */ @activestarttimeofday int = 0, @activeendtimeofday int = 235959, /* No end time */ @newagentid int = 0 OUTPUT ) AS SET NOCOUNT ON /* ** Declarations. */ DECLARE @retcode int DECLARE @distributor sysname DECLARE @distribdb sysname DECLARE @distproc nvarchar (255) DECLARE @agentname nvarchar(100) DECLARE @database sysname DECLARE @newid int DECLARE @mergepublish_bit smallint DECLARE @centralpublish_bit int DECLARE @fFoundPublication int DECLARE @agent_args nvarchar(4000) DECLARE @snapshot_jobid binary(16) DECLARE @dist_rpcname sysname DECLARE @publication_type int /* ** Initializations */ select @mergepublish_bit = 4 select @centralpublish_bit = 1 select @fFoundPublication = 0 EXEC @retcode = dbo.sp_helppublication @publication, @fFoundPublication output IF @@ERROR <> 0 OR @retcode <> 0 BEGIN RETURN (1) END IF @fFoundPublication = 0 BEGIN SELECT @newagentid = 0 RETURN (0) END /* ** Make sure the publication does not already have a agent. */ IF EXISTS (SELECT * FROM syspublications WHERE name = @publication and snapshot_jobid <> NULL) BEGIN RAISERROR (14101, 11, -1, @publication) RETURN(1) END /* Get publication_type */ SELECT @publication_type = repl_freq from syspublications WHERe name = @publication /* ** Get distributor information */ EXEC @retcode = dbo.sp_helpdistributor @distributor = @distributor OUTPUT, @distribdb = @distribdb OUTPUT, @rpcsrvname = @dist_rpcname OUTPUT IF @@error <> 0 OR @retcode <> 0 or @distributor IS NULL OR @distribdb IS NULL BEGIN RAISERROR (14071, 16, -1) RETURN (1) END SELECT @database = DB_NAME() SELECT @distproc = RTRIM(@dist_rpcname) + '.' + @distribdb + '.dbo.sp_MSadd_snapshot_agent' SELECT @agent_args = '-Publisher ' + QUOTENAME(@@SERVERNAME) SELECT @agent_args = @agent_args + ' -PublisherDB ' + QUOTENAME(@database) SELECT @agent_args = @agent_args + ' -Distributor ' + QUOTENAME(@distributor) SELECT @agent_args = @agent_args + ' -Publication ' + QUOTENAME(@publication) BEGIN TRAN EXECUTE @retcode = @distproc @publisher = @@SERVERNAME, @publisher_db = @database, @publication = @publication, @publication_type = @publication_type, @local_job = 1, @freqtype = @freqtype, @freqinterval = @freqinterval, @freqsubtype = @freqsubtype, @freqsubinterval = @freqsubinterval, @freqrelativeinterval = @freqrelativeinterval, @freqrecurrencefactor = @freqrecurrencefactor, @activestartdate = @activestartdate, @activeenddate = @activeenddate, @activestarttimeofday = @activestarttimeofday, @activeendtimeofday = @activeendtimeofday, @command = @agent_args, @snapshot_jobid = @snapshot_jobid OUTPUT IF @@ERROR <> 0 or @retcode <> 0 GOTO UNDO -- Legacy, use non zero taskid to indicate agent already created at the distributor. UPDATE syspublications set snapshot_jobid = @snapshot_jobid WHERE name = @publication IF @@ERROR <> 0 GOTO UNDO -- This is the output parameter to indicate agent created. SELECT @newagentid = 1 COMMIT TRAN return (0) UNDO: if @@TRANCOUNT = 1 ROLLBACK TRAN else COMMIT TRAN return(1) GO EXEC dbo.sp_MS_marksystemobject sp_MSaddpub_snapshot GO dump tran master with no_log GO /* ** SyncTran support procs */ print '' print 'Creating procedure sp_MSis_col_replicated' go create proc sp_MSis_col_replicated @publication sysname, @article sysname, @coltype nvarchar(10) = 'timestamp', -- identity or timestamp @colname sysname = NULL OUTPUT as begin declare @word tinyint, @bit tinyint, @mask binary(2), @mval int, @colword binary(2), @columns binary(32), @firstcol tinyint, @colid smallint, @tabid int, @pubid int select @colname = NULL select @pubid = pubid from syspublications where name = @publication select @tabid = objid from sysarticles where name = @article and pubid = @pubid if @coltype = 'timestamp' begin if ObjectProperty(@tabid, 'TableHasTimestamp') = 1 begin select @colname = name, @colid = colid from syscolumns where id = @tabid and type_name(xtype) = 'timestamp' if @colname is not NULL begin -- check if timestamp is replicated -- Obtain the byte offset and the bit offset, then set the select @columns=columns from sysarticles where name = @article and pubid = @pubid select @word = CONVERT(tinyint, 16 - FLOOR((@colid-1)/16)) select @bit = (@colid-1) % 16 select @mval = POWER(2, @bit) select @mask = convert( binary(2), substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) ) -- Fish out the byte we're interested in and save it in a -- a temporary local variable. select @colword = convert( binary(2), SUBSTRING( convert(nchar(16),@columns), @word, 1) ) if convert( smallint, @colword ) & convert( smallint, @mask) = 0 begin select @colname = NULL return (0) end else return (1) end else begin select @colname = NULL return (0) end end else begin select @colname = NULL return (0) end end else if @coltype = 'identity' begin if ObjectProperty(@tabid, 'TableHasIdentity') = 1 begin select @colname = name, @colid = colid from syscolumns where id = @tabid and ColumnProperty(@tabid, name, 'IsIdentity') = 1 if @colname is not NULL begin -- check if column is replicated -- Obtain the byte offset and the bit offset, then set the select @columns=columns from sysarticles where name = @article and pubid = @pubid select @word = CONVERT(tinyint, 16 - FLOOR((@colid-1)/16)) select @bit = (@colid-1) % 16 select @mval = POWER(2, @bit) select @mask = convert( binary(2), substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) ) -- Fish out the byte we're interested in and save it in a -- a temporary local variable. select @colword = convert( binary(2), SUBSTRING( convert(nchar(16),@columns), @word, 1) ) if convert( smallint, @colword ) & convert( smallint, @mask) = 0 begin select @colname = NULL return (0) end else return (1) end else begin select @colname = NULL return (0) end end else begin select @colname = NULL return (0) end end else begin select @colname = NULL return (0) end end go EXEC dbo.sp_MS_marksystemobject sp_MSis_col_replicated GO print '' print 'Creating procedure sp_MSis_pk_col' go create proc sp_MSis_pk_col @source_table sysname, @colname sysname, @indid int as begin declare @indkey int select @indkey = 1 while @indkey < 16 and index_col(@source_table, @indid, @indkey) is not null begin if index_col(@source_table, @indid, @indkey) = @colname return (1) select @indkey = @indkey + 1 end return (0) end EXEC dbo.sp_MS_marksystemobject sp_MSis_pk_col GO print '' print 'Creating procedure sp_MSmark_proc_norepl' go create procedure sp_MSmark_proc_norepl @procname sysname as set nocount on -- CHECK PERMISSIONS (MUST BE DBO) -- if not (is_member('db_owner')=1 or is_srvrolemember('sysadmin') = 1) begin raiserror(20521,0,1) return 1 end -- CHECK THE OBJECT NAME -- if object_id(@procname, 'local') is null begin raiserror(20522,0,1,@procname) return 1 end -- DO THE UPDATE -- begin tran exec dbo.sp_replupdateschema @procname update sysobjects set replinfo = replinfo | 0x40 where id = object_id(@procname, 'local') commit tran return @@error go EXEC dbo.sp_MS_marksystemobject sp_MSmark_proc_norepl GO create procedure sp_MSdrop_expired_subscription AS /* ** This stored procedure is to periodically check the status of all the subscriptions ** of every merge publication. If any of them is out-of-date, i.e., has lost contact ** with publisher for a certain length of time, we can declare the death of that replica ** and cleanup their traces at the publisher side */ declare @independent_agent bit declare @article sysname declare @publication sysname declare @pubid int declare @artid int declare @publisher sysname declare @subscriber sysname declare @subscriber_id smallint declare @subscriber_db sysname declare @publisher_db sysname declare @out_of_date int declare @distributor sysname declare @distribdb sysname declare @retention int -- in days declare @retcode smallint declare @distproc nvarchar(255) declare @localproc nvarchar(255) declare @msg nvarchar(255) declare @open_cursor nvarchar(400) /* ** Security Check */ EXEC @retcode = dbo.sp_MSreplcheck_publish IF @@ERROR <> 0 or @retcode <> 0 return (1) /* ** Get distribution server information for remote RPC call. */ EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distribdb OUTPUT IF @@ERROR <> 0 or @retcode <> 0 BEGIN RAISERROR (20036, 16, -1) return (1) END SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MShelp_subscription_status ' select @publisher = @@SERVERNAME select @publisher_db = db_name() declare PC CURSOR LOCAL FAST_FORWARD for select DISTINCT name, pubid, independent_agent, retention from syspublications p open PC fetch PC into @publication, @pubid, @independent_agent, @retention WHILE (@@fetch_status <> -1) BEGIN declare SC CURSOR LOCAL FAST_FORWARD for select s.srvid, s.dest_db, a.name from syssubscriptions s, sysarticles a where a.pubid= @pubid and s.artid = a.artid and s.srvid<>-1 for read only open SC fetch SC into @subscriber_id, @subscriber_db, @article WHILE (@@fetch_status <> -1) BEGIN select @subscriber=srvname from master..sysservers where srvid=@subscriber_id exec @retcode = @distproc @publisher = @publisher, @publisher_db = @publisher_db, @publication = @publication, @subscriber = @subscriber, @subscriber_db = @subscriber_db, @retention = @retention, @out_of_date = @out_of_date OUTPUT, @independent_agent = @independent_agent if @retcode<>0 or @@ERROR<>0 begin close SC deallocate SC close PC deallocate PC return (1) end IF (@out_of_date = 1) begin exec @retcode = dbo.sp_dropsubscription -- publisher_db.dbo.sp_dropsubscription @publication = @publication, @article = @article, @subscriber = @subscriber, @destination_db = @subscriber_db if @retcode <>0 or @@ERROR<>0 begin close SC deallocate SC close PC deallocate PC return (1) end raiserror(14157, 10, -1, @subscriber, @publication) end fetch SC into @subscriber_id, @subscriber_db, @article END CLOSE SC DEALLOCATE SC fetch PC into @publication, @pubid, @independent_agent, @retention END CLOSE PC DEALLOCATE PC GO EXEC dbo.sp_MS_marksystemobject sp_MSdrop_expired_subscription go -- synctran supporting procs raiserror('Creating procedure sp_MSscript_insert_statement', 0,1) go create procedure sp_MSscript_insert_statement @objid int, @columns binary(32) as declare @cmd nvarchar(4000) declare @cmd2 nvarchar(4000) declare @qualname nvarchar(512) declare @colname sysname declare @typestring nvarchar(4000) declare @spacer nvarchar(1) declare @ccoltype sysname declare @src_cols int declare @this_col int declare @art_col int declare @rc int declare @num_col int select @src_cols = count(*) from syscolumns where id = @objid exec sp_MSget_qualified_name @objid, @qualname OUTPUT select @cmd2 = N'insert into ' + @qualname + N'( ' -- col names select @spacer = N' ' select @this_col = 1 select @art_col = 1 select @cmd = N'' 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 and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1) begin if rtrim(@ccoltype) not like N'timestamp' and ColumnProperty(@objid, @colname, 'IsIdentity') != 1 begin select @num_col = @num_col + 1 if @cmd2 is not null begin exec dbo.sp_MSflush_command @cmd2 output, 1 select @cmd2 = null end select @cmd = @cmd + @spacer + QUOTENAME(@colname) select @spacer = N',' exec dbo.sp_MSflush_command @cmd output, 0 end end select @this_col = @this_col + 1 end if @num_col > 0 begin -- save off cmd fragment exec dbo.sp_MSflush_command @cmd output, 1 insert into #proctext(procedure_text) values( N') values (') -- col values select @spacer = N' ' select @this_col = 1 select @art_col = 1 select @cmd = N'' while @this_col <= @src_cols begin exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output if @rc = 0 and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1) begin if rtrim(@ccoltype) not like N'timestamp' and ColumnProperty(@objid, @colname, 'IsIdentity') != 1 begin select @cmd = @cmd + @spacer + N'@c' + convert(varchar(4), @this_col) select @spacer = N',' end end exec dbo.sp_MSflush_command @cmd output, 0 select @this_col = @this_col + 1 end -- save off cmd fragment exec dbo.sp_MSflush_command @cmd output, 1 insert into #proctext(procedure_text) values( N') ') end else -- set the @@rowcount insert into #proctext(procedure_text) values( N' select @retcode = @retcode ') go EXEC dbo.sp_MS_marksystemobject sp_MSscript_insert_statement GO raiserror('Creating procedure sp_MSscript_update_statement', 0,1) go create procedure sp_MSscript_update_statement @publication sysname, @article sysname, @objid int, @columns binary(32) as declare @cmd nvarchar(4000) declare @cmd2 nvarchar(4000) declare @qualname nvarchar(512) declare @colname sysname declare @typestring nvarchar(4000) declare @spacer nvarchar(1) declare @ccoltype sysname declare @src_cols int declare @this_col int declare @rc int declare @column nvarchar(100) declare @num_col int select @src_cols = count(*) from syscolumns where id = @objid exec sp_MSget_qualified_name @objid, @qualname OUTPUT select @cmd2 = N'update ' + @qualname + N' set' -- col names select @spacer = N' ' select @this_col = 1 select @cmd = N'' -- If the table have only identity in pk and a ts col, update statement will be empty -- and the query will fail. Prevent it here. select @num_col = 0 -- script update while @this_col <= @src_cols begin exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output if @rc = 0 and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1) begin if rtrim(@ccoltype) not like N'timestamp' and ColumnProperty(@objid, @colname, 'IsIdentity') != 1 begin if @cmd2 is not null begin exec dbo.sp_MSflush_command @cmd2 output, 1 select @cmd2 = null end select @num_col = @num_col + 1 -- Optimization: -- Get null or actual column name -- Note: the output is quoted. exec dbo.sp_MSget_synctran_column @ts_col = null, @op_type = null , -- 'ins, 'upd', 'del' @is_new = null, @primary_key_bitmap = null, @colname = @colname, @this_col = @this_col, @column = @column output, @from_proc = 1 select @cmd = @cmd + @spacer + QUOTENAME(@colname) + N' = ' + @column select @spacer = N',' -- flush command if necessary exec dbo.sp_MSflush_command @cmd output, 0 end end select @this_col = @this_col + 1 end -- save off cmd fragment if @num_col > 0 begin exec dbo.sp_MSflush_command @cmd output, 1 -- Determine method of conflict detection and add where clause if ObjectProperty(@objid, 'TableHasTimestamp') = 1 begin exec @rc = dbo.sp_MSis_col_replicated @publication, @article, 'timestamp', @colname OUTPUT if @rc = 1 begin insert into #proctext(procedure_text) values( N' ') exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd ts', @colname, 4 end end else begin insert into #proctext(procedure_text) values( N' ') exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd rc', null, 4 end end else -- set the @@rowcount insert into #proctext(procedure_text) values( N' select @retcode = @retcode ') go EXEC dbo.sp_MS_marksystemobject sp_MSscript_update_statement GO raiserror('Creating procedure sp_MSscript_delete_statement', 0,1) go create procedure sp_MSscript_delete_statement @publication sysname, @article sysname, @objid int, @columns binary(32) as declare @cmd nvarchar(4000) declare @qualname nvarchar(512) declare @colname sysname declare @typestring nvarchar(4000) declare @spacer nvarchar(1) declare @ccoltype sysname declare @src_cols int declare @this_col int declare @art_col int declare @rc int select @src_cols = count(*) from syscolumns where id = @objid exec sp_MSget_qualified_name @objid, @qualname OUTPUT select @cmd = N'delete ' + @qualname exec dbo.sp_MSflush_command @cmd output, 1 -- Determine method of conflict detection and add where clause insert into #proctext(procedure_text) values( N' ') if ObjectProperty(@objid, 'TableHasTimestamp') = 1 begin exec @rc = dbo.sp_MSis_col_replicated @publication, @article, 'timestamp', @colname OUTPUT if @rc = 1 exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd ts', @colname, 4 else exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd rc', null, 4 end else exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd rc', null, 4 go EXEC dbo.sp_MS_marksystemobject sp_MSscript_delete_statement GO raiserror('Creating procedure sp_MSscript_beginproc', 0,1) go create procedure sp_MSscript_beginproc @publication sysname, @article sysname, @procname sysname, @source_objid int output, @columns binary(32) output as declare @cmd nvarchar(4000) declare @source_table sysname declare @owner sysname -- Retrieve underlying table name and replicated columns select @source_table = object_name(objid), @source_objid = objid, @columns = columns from sysarticles a, syspublications p where a.name = @article and p.name = @publication and a.pubid = p.pubid -- Get the object owner name select @owner = u.name from sysusers u, sysobjects o where o.id = @source_objid and o.uid = u.uid if @source_table IS NULL begin raiserror (20506, 16, 1, @source_table, 'sp_MSscript_beginproc') return 0 end -- Construct proc name -- Create proc under the table owner account to preserve the ownership chain select @cmd = N'create procedure '+QUOTENAME(@owner)+ N'.'+ QUOTENAME(@procname) + N' @orig_server sysname, @orig_db sysname, ' exec dbo.sp_MSflush_command @cmd output, 1 return 1 go EXEC dbo.sp_MS_marksystemobject sp_MSscript_beginproc GO raiserror('Creating procedure sp_MSscript_security', 0,1) go create procedure sp_MSscript_security @publication sysname as declare @cmd nvarchar(4000) -- insert into #proctext(procedure_text) values(N'declare @retcode int') insert into #proctext(procedure_text) values(N'exec @retcode = dbo.sp_MSreplcheck_pull') insert into #proctext(procedure_text) values(N'@publication = ''' + @publication + ''' ' ) insert into #proctext(procedure_text) values(N'if @retcode <> 0 or @@error <> 0' ) insert into #proctext(procedure_text) values(N' return -1 ') go EXEC dbo.sp_MS_marksystemobject sp_MSscript_security GO raiserror('Creating procedure sp_MSscript_endproc', 0,1) go create procedure sp_MSscript_endproc @objid int, @op_type varchar(3) = 'ins', -- 'ins', 'upd', 'del' @columns binary(32), @outvars nvarchar(4000) as declare @cmd nvarchar(4000) declare @qualname nvarchar(512) exec sp_MSget_qualified_name @objid, @qualname OUTPUT insert into #proctext(procedure_text) values(N' if @@ROWCOUNT = 0 begin exec sp_MSreplraiserror 20515 return -1 end') if @outvars <> null begin insert into #proctext(procedure_text) values(N' else begin ') if @op_type = 'upd' -- Script out pk var assigment that used in sp_MSscript_where_clause exec dbo.sp_MSscript_pkvar_assignment @objid, @columns, 1 insert into #proctext(procedure_text) values(N' ') select @cmd = N' select ' + @outvars insert into #proctext(procedure_text) values( @cmd) select @cmd = N' from ' + @qualname insert into #proctext(procedure_text) values( @cmd) insert into #proctext(procedure_text) values( N' ') if @op_type = 'ins' exec dbo.sp_MSscript_where_clause @objid, @columns, 'new pk', null, 4 else if @op_type = 'upd' exec dbo.sp_MSscript_where_clause @objid, @columns, 'old pk', null, 4 insert into #proctext(procedure_text) values( N' return 0 ') insert into #proctext(procedure_text) values( N'end ') end else begin insert into #proctext(procedure_text) values( N' else return 0') end go EXEC dbo.sp_MS_marksystemobject sp_MSscript_endproc GO raiserror('Creating procedure sp_MStable_not_modifiable', 0,1) go create proc sp_MStable_not_modifiable @objid int, @columns binary(32) as declare @colname sysname declare @typestring nvarchar(4000) declare @src_cols int declare @this_col int declare @art_col int declare @isset int declare @found int, @repl_columns int select @this_col = 1 select @art_col = 1 select @found = 0, @repl_columns = 0 select @src_cols = count(*) from syscolumns where id = @objid while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns if @isset != 0 and EXISTS (select name from syscolumns where id=@objid and @this_col=colid and iscomputed<>1) begin select @repl_columns = @repl_columns + 1 exec dbo.sp_MSget_type @objid, @this_col, @colname output, @typestring OUTPUT if @typestring = N'timestamp' or ColumnProperty(@objid, @colname, 'IsIdentity') = 1 select @found = 1 end select @this_col = @this_col + 1 end if @found = 1 and @repl_columns = 1 return 1 else return 0 go EXEC dbo.sp_MS_marksystemobject sp_MStable_not_modifiable GO raiserror('Creating procedure sp_MSscript_sync_ins_proc', 0,1) go create procedure sp_MSscript_sync_ins_proc @publication sysname, @article sysname, @procname sysname as declare @source_objid int declare @colname sysname declare @indid int declare @cmd nvarchar(4000) declare @ins_cmd nvarchar(4000) declare @columns binary(32) declare @outvars nvarchar(4000) declare @rc int set nocount on -- Create temp table create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL) -- preamble common to all synctran procs exec @rc = dbo.sp_MSscript_beginproc @publication, @article, @procname, @source_objid output, @columns output if @rc = 0 return -- construct parameter list exec dbo.sp_MSscript_params @source_objid, @columns, null, 1, @outvars output -- construct body of procedure insert into #proctext(procedure_text) values( N' as ') -- set cycle detection insert into #proctext(procedure_text) values(N'declare @retcode int ') insert into #proctext(procedure_text) values( N'exec @retcode = dbo.sp_replsetoriginator @orig_server, @orig_db ') insert into #proctext(procedure_text) values( N'if @retcode <> 0 or @@error <> 0 return -1 ') -- script out security check exec dbo.sp_MSscript_security @publication -- Work around for case where article has 1 col that is not user-modfied (identity, timestamp) exec @rc = dbo.sp_MStable_not_modifiable @source_objid, @columns if @rc = 1 insert into #proctext(procedure_text) values( N'exec sp_MSreplraiserror 20516 ') else begin exec @indid = dbo.sp_MStable_has_unique_index @source_objid if @outvars <> null and @indid = 0 -- no insert/update allowed if timestamp/identity col and no unique index insert into #proctext(procedure_text) values( N'exec sp_MSreplraiserror 20516 ') else begin -- script insert statemnt exec dbo.sp_MSscript_insert_statement @source_objid, @columns -- script closing exec dbo.sp_MSscript_endproc @source_objid, 'ins', @columns, @outvars end end -- send fragments to client select procedure_text from #proctext order by c1 asc go EXEC dbo.sp_MS_marksystemobject sp_MSscript_sync_ins_proc GO raiserror('Creating procedure sp_MSscript_sync_upd_proc', 0,1) go create procedure sp_MSscript_sync_upd_proc @publication sysname, @article sysname, @procname sysname as declare @source_objid int declare @colname sysname declare @indid int declare @cmd nvarchar(4000) declare @ins_cmd nvarchar(4000) declare @columns binary(32) declare @outvars nvarchar(4000) declare @rc int set nocount on -- Create temp table create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL) -- preamble common to all synctran procs exec @rc = dbo.sp_MSscript_beginproc @publication, @article, @procname, @source_objid output, @columns output if @rc = 0 return -- construct parameter list exec dbo.sp_MSscript_params @source_objid, @columns, null, 1, @outvars output insert into #proctext(procedure_text) values( N', ') exec dbo.sp_MSscript_params @source_objid, @columns, N'_old', 0, null -- Script bitmap parameter insert into #proctext(procedure_text) values( N', @bitmap varbinary(4000)') -- construct body of procedure insert into #proctext(procedure_text) values( N' as ') -- set cycle detection insert into #proctext(procedure_text) values(N'declare @retcode int ') insert into #proctext(procedure_text) values( N'exec @retcode = dbo.sp_replsetoriginator @orig_server, @orig_db ') insert into #proctext(procedure_text) values( N'if @retcode <> 0 or @@error <> 0 return -1 ') -- script out security check exec dbo.sp_MSscript_security @publication -- Work around for case where article has 1 col that is not user-modfied (identity, timestamp) exec @rc = dbo.sp_MStable_not_modifiable @source_objid, @columns if @rc = 1 insert into #proctext(procedure_text) values( N'exec sp_MSreplraiserror 20516 ') else begin exec @indid = dbo.sp_MStable_has_unique_index @source_objid if @outvars <> null and @indid = 0 -- no insert/update allowed if timestamp/identity col and no unique index insert into #proctext(procedure_text) values( N'exec sp_MSreplraiserror 20516 ') else begin -- script update statemnt exec dbo.sp_MSscript_update_statement @publication, @article, @source_objid, @columns -- script closing exec dbo.sp_MSscript_endproc @source_objid, 'upd', @columns, @outvars end end -- send fragments to client select procedure_text from #proctext order by c1 asc go EXEC dbo.sp_MS_marksystemobject sp_MSscript_sync_upd_proc GO raiserror('Creating procedure sp_MSscript_sync_del_proc', 0,1) go create procedure sp_MSscript_sync_del_proc @publication sysname, @article sysname, @procname sysname as declare @source_objid int declare @colname sysname declare @indid int declare @cmd nvarchar(4000) declare @ins_cmd nvarchar(4000) declare @columns binary(32) declare @outvars nvarchar(4000) declare @rc int set nocount on -- Create temp table create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL) -- preamble common to all synctran procs exec @rc = dbo.sp_MSscript_beginproc @publication, @article, @procname, @source_objid output, @columns output if @rc = 0 return -- construct parameter list exec dbo.sp_MSscript_params @source_objid, @columns, N'_old', 0, null -- construct body of procedure insert into #proctext(procedure_text) values( N' as ') -- set cycle detection insert into #proctext(procedure_text) values(N'declare @retcode int ') insert into #proctext(procedure_text) values( N'exec @retcode = dbo.sp_replsetoriginator @orig_server, @orig_db ') insert into #proctext(procedure_text) values( N'if @retcode <> 0 or @@error <> 0 return -1 ') -- script out security check exec dbo.sp_MSscript_security @publication -- Work around for case where article has 1 col that is not user-modfied (identity, timestamp) exec @rc = dbo.sp_MStable_not_modifiable @source_objid, @columns if @rc = 1 insert into #proctext(procedure_text) values( N'exec sp_MSreplraiserror 20516 ') else begin exec @indid = dbo.sp_MStable_has_unique_index @source_objid if @indid = 0 -- no delete allowed if no unique index insert into #proctext(procedure_text) values( N'exec sp_MSreplraiserror 20516 ') else begin -- script insert statemnt exec dbo.sp_MSscript_delete_statement @publication, @article, @source_objid, @columns -- script closing exec dbo.sp_MSscript_endproc @source_objid, 'del', @columns, null end end -- send fragments to client select procedure_text from #proctext order by c1 asc go EXEC dbo.sp_MS_marksystemobject sp_MSscript_sync_del_proc GO print '' print 'Creating procedure sp_MSgen_sync_tran_procs' go create procedure sp_MSgen_sync_tran_procs @publication sysname, -- table name @article sysname, @ins_proc sysname, @upd_proc sysname, @del_proc sysname as set nocount on declare @cmd nvarchar(4000) declare @dbname sysname declare @owner sysname declare @retcode int select @owner = user_name(o.uid) from sysobjects o , sysarticles a where o.id=a.objid and a.name=@article -- We are now going to create procs, so start a transaction begin tran gen_procs -- Call out to individual create proc routines select @dbname = db_name() select @cmd = 'sp_MSscript_sync_ins_proc [' + @publication + '], [' + @article + '], [' + @ins_proc + ']' exec master..xp_execresultset @cmd, @dbname select @cmd = 'sp_MSscript_sync_upd_proc [' + @publication + '], [' + @article + '], [' + @upd_proc + ']' exec master..xp_execresultset @cmd, @dbname select @cmd = 'sp_MSscript_sync_del_proc [' + @publication + '], [' + @article + '], [' + @del_proc + ']' exec master..xp_execresultset @cmd, @dbname -- Grant permissions select @cmd = 'grant exec on ' + quotename(@owner) + '.' + quotename(@ins_proc) + ' to public' exec (@cmd) select @cmd = 'grant exec on ' + quotename(@owner) + '.' + quotename(@upd_proc) + ' to public' exec (@cmd) select @cmd = 'grant exec on ' + quotename(@owner) + '.' + quotename(@del_proc) + ' to public' exec (@cmd) -- Mark procedures as system procs so they don't show up in the UI if @owner in ('dbo','INFORMATION_SCHEMA') begin select @cmd = 'exec dbo.sp_MS_marksystemobject ''' + quotename(@owner) + '.' + quotename(@ins_proc) + '''' exec (@cmd) select @cmd = 'exec dbo.sp_MS_marksystemobject ''' + quotename(@owner) + '.' + quotename(@upd_proc) + '''' exec (@cmd) select @cmd = 'exec dbo.sp_MS_marksystemobject ''' + quotename(@owner) + '.' + quotename(@del_proc) + '''' exec (@cmd) end -- Mark procedures to set 'NOT FOR REPL' bit select @cmd = 'exec dbo.sp_MSmark_proc_norepl ''' + quotename(@owner) + '.' + quotename(@ins_proc) + '''' exec (@cmd) select @cmd = 'exec dbo.sp_MSmark_proc_norepl ''' + quotename(@owner) + '.' + quotename(@upd_proc) + '''' exec (@cmd) select @cmd = 'exec dbo.sp_MSmark_proc_norepl ''' + quotename(@owner) + '.' + quotename(@del_proc) + '''' exec (@cmd) -- Commit tran commit tran go EXEC dbo.sp_MS_marksystemobject sp_MSgen_sync_tran_procs GO print '' print 'Creating procedure sp_articlesynctranprocs' go CREATE PROCEDURE sp_articlesynctranprocs @publication sysname, -- publication name @article sysname, -- article name @ins_proc sysname, -- name of sproc supporting Sync Tran inserts associated with this article @upd_proc sysname, -- name of sproc supporting Sync Tran updates associated with this article @del_proc sysname, -- name of sproc supporting Sync Tran deletes associated with this article @autogen nvarchar(5) = 'true' -- indicates wether or not to auto generate sprocs AS SET NOCOUNT ON -- Declarations. DECLARE @pubid int DECLARE @artid int DECLARE @retcode int DECLARE @autogen_id bit DECLARE @ins_proc_id int DECLARE @upd_proc_id int DECLARE @del_proc_id int /* ** Security Check. */ exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) -- Parameter Check: @article. The @article name cannot be NULL and must conform -- to the rules for identifiers. IF @article IS NULL BEGIN RAISERROR (14043, 16, -1, '@article') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @article IF @retcode <> 0 RETURN(1) -- Parameter Check: @publication. -- The @publication name cannot be NULL and must conform to the rules -- for identifiers. IF @publication IS NULL BEGIN RAISERROR (14043, 16, -1, '@publication') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @publication IF @retcode <> 0 RETURN (1) -- Parameter Check: @ins_proc, @upd_proc, @del_proc. -- The sproc names cannot be NULL and must conform to the rules -- for identifiers IF @ins_proc IS NULL BEGIN RAISERROR (14043, 16, -1, '@ins_proc') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @ins_proc IF @retcode <> 0 RETURN (1) IF @upd_proc IS NULL BEGIN RAISERROR (14043, 16, -1, '@upd_proc') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @upd_proc IF @retcode <> 0 RETURN (1) IF @del_proc IS NULL BEGIN RAISERROR (14043, 16, -1, '@del_proc') RETURN (1) END EXECUTE @retcode = dbo.sp_validname @del_proc IF @retcode <> 0 RETURN (1) -- Parameter Check: @autogen IF @autogen IS NULL OR LOWER(@autogen) NOT IN ('true', 'false') BEGIN RAISERROR (14148, 16, -1, '@autogen') RETURN (1) END IF LOWER(@autogen) = 'true' SELECT @autogen_id = 1 ELSE SELECT @autogen_id = 0 -- Retrieve pubid & artid SELECT @pubid = a.pubid, @artid = a.artid FROM sysarticles a, syspublications p WHERE p.name = @publication AND a.name = @article AND a.pubid = p.pubid IF @pubid IS NULL OR @artid IS NULL BEGIN if @pubid IS NULL RAISERROR (20026, 16, 1, @publication) if @artid IS NULL RAISERROR (20026, 16, 1, @publication) RETURN (1) END BEGIN TRAN sp_articlesynctranprocs -- if @autogen is true, generate the sprocs IF @autogen_id = 1 BEGIN EXECUTE @retcode = dbo.sp_MSgen_sync_tran_procs @publication, @article, @ins_proc, @upd_proc, @del_proc IF @retcode <> 0 BEGIN IF @@TRANCOUNT <> 0 ROLLBACK tran sp_articlesynctranprocs RETURN (1) END END --retrieve sproc id's, fail if they don't exist SELECT @ins_proc_id = id FROM sysobjects WHERE name = @ins_proc SELECT @upd_proc_id = id FROM sysobjects WHERE name = @upd_proc SELECT @del_proc_id = id FROM sysobjects WHERE name = @del_proc IF (@ins_proc_id IS NULL) OR (@upd_proc_id IS NULL) OR (@del_proc_id IS NULL) BEGIN if @ins_proc_id IS NULL RAISERROR (20500, 16, 1, @ins_proc) if @upd_proc_id IS NULL RAISERROR (20500, 16, 1, @upd_proc) if @del_proc_id IS NULL RAISERROR (20500, 16, 1, @del_proc) IF @@TRANCOUNT <> 0 ROLLBACK tran sp_articlesynctranprocs RETURN (1) END -- perform insert into sysarticleupdates -- BUGUBG need to mark this as a system table, so this sproc can live in master db INSERT sysarticleupdates(pubid, artid, sync_ins_proc, sync_upd_proc, sync_del_proc, autogen) VALUES (@pubid, @artid, @ins_proc_id, @upd_proc_id, @del_proc_id, @autogen_id) IF @@ERROR <> 0 BEGIN IF @@TRANCOUNT <> 0 ROLLBACK tran sp_articlesynctranprocs RETURN (1) END COMMIT TRAN go EXEC dbo.sp_MS_marksystemobject sp_articlesynctranprocs GO print '' print 'Creating procedure sp_reinitsubscription' go CREATE PROCEDURE sp_reinitsubscription ( @publication sysname = 'all', /* publication name */ @article sysname = 'all', /* article name */ -- Force user to specify the subscriber name @subscriber sysname, /* subscriber name */ @destination_db sysname = 'all' /* destination database name */ ) AS DECLARE @retcode int DECLARE @distributor sysname DECLARE @distribdb sysname declare @active tinyint declare @subscribed tinyint declare @automatic tinyint DECLARE @artid int DECLARE @srvid smallint DECLARE @distproc nvarchar (255) DECLARE @dbname sysname DECLARE @sub_ts binary(10) -- must be binary(10) type. DECLARE @sync_type tinyint DECLARE @immediate_sync bit DECLARE @subscription_type int DECLARE @push int DECLARE @pub sysname DECLARE @dest_db sysname DECLARE @sub_name sysname DECLARE @art_name sysname DECLARE @none tinyint declare @login_name sysname -- Initialization select @active = 2 select @subscribed = 1 select @dbname = DB_NAME() SELECT @none = 2 /* Const: synchronization type 'none' */ SELECT @automatic = 1 /* Const: synchronization type 'automatic' */ select @push = 0 /* ** Security Check. ** We use login_name stored in syssubscriptions to manage security */ /* Validate names */ EXECUTE @retcode = dbo.sp_validname @publication IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) /* article name can be a quoted name EXECUTE @retcode = dbo.sp_validname @article IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) */ -- Subscriber can be NULL IF @subscriber IS NOT NULL BEGIN EXECUTE @retcode = dbo.sp_validname @subscriber IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) EXECUTE @retcode = dbo.sp_validname @destination_db IF @@ERROR <> 0 OR @retcode <> 0 RETURN (1) END -- Replace 'all' with '%' if LOWER(@publication) = 'all' SELECT @publication = '%' if LOWER(@article) = 'all' SELECT @article = '%' if LOWER(@subscriber) = 'all' SELECT @subscriber = '%' if LOWER(@destination_db) = 'all' SELECT @destination_db = '%' /* ** Parameter Check: @publication ** Check to make sure that the publication exists, that it's not NULL, ** and that it conforms to the rules for identifiers. */ IF NOT EXISTS (SELECT * FROM syspublications WHERE name LIKE @publication) BEGIN IF @publication = '%' RAISERROR (14008, 11, -1) ELSE RAISERROR (20026, 11, -1, @publication) RETURN (1) END /* ** Parameter Check: @article ** Check to make sure that the article exists, that it's not null, ** and that it conforms to the rules for identifiers. */ IF NOT EXISTS (SELECT * FROM sysarticles a, syspublications b WHERE a.name LIKE @article AND a.pubid = b.pubid AND b.name LIKE @publication) BEGIN IF @article = '%' RAISERROR (14009, 11, -1, @publication) ELSE RAISERROR (20027, 11, -1, @article) RETURN (1) END -- Don't check subscriber and dest_db for virtual subscriptions IF @subscriber IS NOT NULL BEGIN /* ** Parameter Check: @subscriber ** Check to make sure that the subscriber exists */ if @subscriber <> '%' select @subscriber = UPPER(@subscriber) IF NOT EXISTS (SELECT * FROM master..sysservers WHERE ((@subscriber = N'%') OR (UPPER(srvname) = UPPER(@subscriber))) AND (srvstatus & 4) <> 0) BEGIN RAISERROR (14063, 11, -1) RETURN (1) END END -- Wrong dest_db will be caught by the following query -- Check to make sure the subscription exists IF @publication <> '%' AND @subscriber <> '%' AND NOT EXISTS (SELECT * FROM syssubscriptions sub, sysarticles art, syspublications pub, master..sysservers ss WHERE pub.name LIKE @publication AND art.name LIKE @article AND ((UPPER(ss.srvname) = UPPER(@subscriber) AND sub.srvid = ss.srvid) OR (@subscriber is NULL AND pub.allow_anonymous = 1)) AND sub.artid = art.artid AND art.pubid = pub.pubid AND sub.dest_db LIKE @destination_db) BEGIN RAISERROR (14055, 16, -1) RETURN (1) END EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT, @distribdb = @distribdb OUTPUT IF @@ERROR <> 0 BEGIN RAISERROR (14071, 16, -1) RETURN (1) END IF @retcode <> 0 OR @distribdb IS NULL OR @distributor IS NULL BEGIN RAISERROR (14071, 16, -1) RETURN (1) END DECLARE hCresyncsub CURSOR LOCAL FAST_FORWARD FOR -- non immediate_sync pubs SELECT pub.name, pub.immediate_sync, art.name, ss.srvname, sub.dest_db, sub.sync_type, sub.subscription_type, sub.login_name FROM syssubscriptions sub, sysarticles art, syspublications pub, master..sysservers ss WHERE pub.name LIKE @publication AND art.name LIKE @article AND ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber))) AND sub.srvid = ss.srvid AND sub.artid = art.artid AND art.pubid = pub.pubid AND sub.dest_db LIKE @destination_db AND sub.status = @active AND pub.immediate_sync = 0 UNION -- Immediate_sync pubs SELECT DISTINCT pub.name, immediate_sync, '%', -- art.name is '%' from immediate_sync pub ss.srvname, sub.dest_db, sub.sync_type, sub.subscription_type, sub.login_name FROM syssubscriptions sub, sysarticles art, syspublications pub, master..sysservers ss WHERE pub.name LIKE @publication -- Ignore @article AND ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber))) AND sub.srvid = ss.srvid AND sub.artid = art.artid AND art.pubid = pub.pubid AND sub.dest_db LIKE @destination_db AND sub.status = @active AND pub.immediate_sync = 1 UNION -- For anonymous subscribers SELECT pub.name, immediate_sync, '%', -- art.name is '%' for immediate_sync pub CONVERT(sysname, NULL), -- subscriber name (null represent virtual) 'virtual', -- destination_db for virtual subscription is hardcoded in -- sp_MSadd_subscription. @automatic, -- sub.sync_type is auto tor anonymous subscriber @push, -- virtual subscription is push type, 'sa' FROM syspublications pub WHERE pub.name LIKE @publication -- Ignore @article AND pub.allow_anonymous = 1 AND (@subscriber = '%' OR @subscriber IS NULL) FOR READ ONLY OPEN hCresyncsub -- Note: Don't overwrite the variables used in the cursor. FETCH hCresyncsub INTO @pub, @immediate_sync, @art_name, @sub_name, @dest_db, @sync_type, @subscription_type, @login_name WHILE (@@fetch_status <> -1) BEGIN -- Security Check IF suser_sname(suser_sid()) <> @login_name AND is_srvrolemember('sysadmin') <> 1 AND is_member ('db_owner') <> 1 BEGIN RAISERROR (14126, 11, -1) RETURN (1) END if @sync_type = @none begin raiserror(21071, 10, -1, @art_name, @sub_name, @dest_db, @pub) FETCH hCresyncsub INTO @pub, @immediate_sync, @art_name, @sub_name, @dest_db, @sync_type, @subscription_type, @login_name continue end -- If @article is not 'all' for immediate_sync publication -- report error and skip. IF @immediate_sync = 1 AND @article != '%' BEGIN RAISERROR (14122, 16, -1) FETCH hCresyncsub INTO @pub, @immediate_sync, @art_name, @sub_name, @dest_db, @sync_type, @subscription_type, @login_name CONTINUE END begin tran save TRAN sp_reinitsubscription -- Reset subscription status to subscribed and activate it later. -- This is to reset its snapshot transaction ts to the new one. -- We don't need to do it for anonymous subscriber since its snapshot -- transaction ts will be updated automatically by the snapshot agent. IF @sub_name IS NOT NULL BEGIN EXEC @retcode = dbo.sp_changesubstatus @publication = @pub, @article = @art_name, @subscriber = @sub_name, @destination_db = @dest_db, @status = 'subscribed' IF @@ERROR <> 0 OR @retcode <> 0 BEGIN CLOSE hCresyncsub DEALLOCATE hCresyncsub RAISERROR (14070, 16, -1) GOTO UNDO END END -- Reset the subscription guid at the distributor for immediate_sync publication. -- Reset subscription creation datetime used by retention cleanup. SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSreset_subscription' EXEC @retcode = @distproc @publisher = @@SERVERNAME, @publisher_db = @dbname, @publication = @pub, @subscriber = @sub_name, @subscriber_db = @dest_db, @subscription_type = @subscription_type IF @@ERROR <> 0 OR @retcode <> 0 BEGIN CLOSE hCresyncsub DEALLOCATE hCresyncsub GOTO UNDO END -- Activate the subscription again if the publication is immediate_sync or -- the subscription is no_sync type. -- Otherwise, the snapshot agent will activate the subscription IF (@immediate_sync = 1 AND @subscriber IS NOT NULL) BEGIN -- Set subscription status back to active again. EXEC @retcode = dbo.sp_changesubstatus @publication = @pub, @article = @art_name, @subscriber = @sub_name, @destination_db = @dest_db, @status = 'active' IF @@ERROR <> 0 OR @retcode <> 0 BEGIN CLOSE hCresyncsub DEALLOCATE hCresyncsub RAISERROR (14070, 16, -1) GOTO UNDO END END COMMIT TRAN FETCH hCresyncsub INTO @pub, @immediate_sync, @art_name, @sub_name, @dest_db, @sync_type, @subscription_type, @login_name END CLOSE hCresyncsub DEALLOCATE hCresyncsub RETURN(0) UNDO: IF @@TRANCOUNT > 0 begin ROLLBACK TRAN sp_reinitsubscription COMMIT TRAN end return 1 go EXEC dbo.sp_MS_marksystemobject sp_reinitsubscription GO dump tran master with no_log GO -------------------------------------------------------------------- -------------------------------------------------------------------- print '' print 'Creating procedure sp_getarticlepkcolbitmap' go create procedure sp_getarticlepkcolbitmap @tabid int, @colbitmap binary(32) output as declare @pkindid int declare @indkey int declare @colid int declare @word tinyint declare @mval int declare @mask binary(2) declare @wordval binary(2) declare @objname nvarchar(265) select @colbitmap = 0x00 select @pkindid = indid from sysindexes where id = @tabid and status & 2048 <> 0 select @indkey = 1 select @objname = QUOTENAME(user_name(OBJECTPROPERTY(@tabid, 'OwnerId'))) + N'.' + QUOTENAME(object_name( @tabid )) while @indkey <= 16 and index_col( @objname, @pkindid, @indkey ) is not null begin select @colid = colid from syscolumns where id = @tabid and name = index_col( @objname, @pkindid, @indkey ) select @word = convert(tinyint, 16 - floor((@colid-1)/16)) select @mval = power(2, (@colid-1) % 16 ) select @mask = convert( binary(2), substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) ) select @wordval = convert( binary(2), substring( convert( nchar(16), @colbitmap ), @word, 1 ) ) select @wordval = convert( binary(2), convert( smallint, @wordval) | convert( smallint, @mask) ) select @colbitmap = convert(binary(32), STUFF( convert(nchar(16),@colbitmap), @word, 1, convert( nchar(1),@wordval))) select @indkey = @indkey + 1 end go EXEC dbo.sp_MS_marksystemobject sp_getarticlepkcolbitmap GO -------------------------------------------------------------------- -------------------------------------------------------------------- print '' print 'Creating procedure sp_gettypestring' go create procedure sp_gettypestring @tabid int, @colid int, @typestring nvarchar(255) output as declare @coltypename sysname declare @coltype tinyint declare @colvar bit declare @collen smallint declare @colprec tinyint declare @colscale tinyint select @coltypename = st.name, @coltype = st.xtype, @colvar = st.variable, @collen = sc.length, @colprec = sc.xprec, @colscale = sc.xscale from systypes st, syscolumns sc where sc.id = @tabid and sc.colid = @colid and st.xtype = sc.xtype and st.xtype = st.xusertype select @typestring = @coltypename if @coltypename in (N'char', N'varchar', N'binary', N'varbinary') begin select @typestring = @typestring + N'(' + convert(nvarchar,@collen) + N')' end else if @coltypename in (N'nchar', N'nvarchar' ) begin select @typestring = @typestring + N'(' + convert(nvarchar,@collen/2) + N')' end else if @coltype = 108 or @coltype = 106 begin select @typestring = @typestring + N'(' + convert(nvarchar,@colprec) + N',' + convert(nvarchar,@colscale) + N')' end else if @coltype = 189 begin select @typestring = N'binary(8)' end go EXEC dbo.sp_MS_marksystemobject sp_gettypestring GO -------------------------------------------------------------------- -------------------------------------------------------------------- print '' print 'Creating procedure sp_isarticlecolbitset' go create procedure sp_isarticlecolbitset @colid int, @colbitmap binary(32) as declare @word tinyint declare @mval int declare @mask smallint select @word = convert(tinyint, 16 - floor((@colid-1)/16)) select @mval = power(2, (@colid-1) % 16 ) select @mask = convert( smallint, convert( binary(2), substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) ) ) if convert( binary(2), substring( convert( nchar(16),@colbitmap), @word, 1 ) ) & @mask = @mask begin return 1 end else begin return 0 end go EXEC dbo.sp_MS_marksystemobject sp_isarticlecolbitset GO -------------------------------------------------------------------- -------------------------------------------------------------------- print '' print 'sp_scriptpkwhereclause' go create procedure sp_scriptpkwhereclause @src_objid int, @src_cols int, @pkcolumns binary(32) as declare @this_col int declare @art_col int declare @spacer nvarchar(10) declare @isset int declare @cmd nvarchar(4000) -- create WHERE clause select @this_col = 1 select @art_col = 1 select @spacer = N' ' select @cmd = N'where' while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1) begin select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = @pkc' + convert( nvarchar, @art_col ) select @art_col = @art_col + 1 select @spacer = N' and ' if len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' end end select @this_col = @this_col + 1 end insert into #proctext(procedure_text) values( @cmd ) go EXEC dbo.sp_MS_marksystemobject sp_scriptpkwhereclause GO -------------------------------------------------------------------- -------------------------------------------------------------------- print '' print 'Create procedure sp_scriptupdateparams' go create procedure sp_scriptupdateparams @src_objid int, @src_cols int, @artcolumns binary(32), @pkcolumns binary(32) as declare @this_col int declare @art_col int declare @spacer nvarchar(10) declare @isset int declare @cmd nvarchar(4000) declare @typestring nvarchar(255) -- add colval parameters select @this_col = 1 select @art_col = 1 select @spacer = N' ' select @cmd = '' while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1) begin exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) + N' ' + @typestring select @art_col = @art_col + 1 select @spacer = N',' if len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' end end select @this_col = @this_col + 1 end -- add pkval parameters select @this_col = 1 select @art_col = 1 while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1) begin exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT select @cmd = @cmd + @spacer + N'@pkc' + convert( nvarchar, @art_col ) + N' ' + @typestring select @art_col = @art_col + 1 select @spacer = N',' if len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' end end select @this_col = @this_col + 1 end insert into #proctext(procedure_text) values ( @cmd ) go EXEC dbo.sp_MS_marksystemobject sp_scriptupdateparams GO -------------------------------------------------------------------- -------------------------------------------------------------------- print '' print 'Creating procedure sp_scriptinsproc' go create procedure sp_scriptinsproc @artid int as declare @cmd nvarchar(4000) declare @dest_owner nvarchar(255) declare @dest_tabname sysname declare @src_objid int declare @columns binary(32) declare @ins_cmd nvarchar(255) declare @dest_proc sysname declare @src_cols int declare @this_col int declare @art_col int declare @isset int declare @typestring nvarchar(255) declare @spacer nvarchar(1) if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 ) begin raiserror (14155, 16, 1 ) return 1 end -------- create temp table for command fragments create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL) -------- get sysarticles information select @dest_owner = dest_owner, @dest_tabname = dest_table, @src_objid = objid, @columns = columns, @ins_cmd = ins_cmd from sysarticles where artid = @artid if @dest_owner is not null begin select @dest_owner = QUOTENAME( @dest_owner ) + N'.' end else begin select @dest_owner = N'' end -------- get dest proc name if( 1 != charindex( N'CALL', upper(@ins_cmd) ) ) or @ins_cmd is null begin raiserror (14156, 16, 1 ) return 1 end select @dest_proc = substring( @ins_cmd, 6, len( @ins_cmd ) - 4 ) select @cmd = N'create procedure ' + QUOTENAME(@dest_proc) -------- construct parameter list select @this_col = 1 select @art_col = 1 select @src_cols = count(*) from syscolumns where id = @src_objid select @spacer = N' ' while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1) begin if len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' end exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) + N' ' + @typestring select @art_col = @art_col + 1 select @spacer = N',' end select @this_col = @this_col + 1 end -- save off cmd fragment insert into #proctext(procedure_text) values( @cmd ) insert into #proctext(procedure_text) values( N'as' ) ------- construct proc body select @cmd = N'insert into ' + @dest_owner + QUOTENAME(@dest_tabname) + N' values (' select @this_col = 1 select @art_col = 1 select @spacer = N' ' while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid) begin if len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' end select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) select @art_col = @art_col + 1 select @spacer = N',' end select @this_col = @this_col + 1 end -- finish up proc body select @cmd = @cmd + N' )' -- save off cmd fragement insert into #proctext(procedure_text) values( @cmd ) -- send fragements to client select procedure_text from #proctext order by c1 asc go EXEC dbo.sp_MS_marksystemobject sp_scriptinsproc GO ---------------------------------------------------- --------------------------------------------------- print '' print 'Creating procedure sp_scriptdelproc' go create procedure sp_scriptdelproc @artid int as declare @cmd nvarchar(4000) declare @dest_owner nvarchar(255) declare @dest_tabname sysname declare @src_objid int declare @pkcolumns binary(32) declare @del_cmd nvarchar(255) declare @dest_proc sysname declare @src_cols int declare @this_col int declare @art_col int declare @isset int declare @typestring nvarchar(255) declare @spacer nvarchar(10) if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 ) begin raiserror (14155, 16, 1 ) return 1 end -------- create temp table for command fragments create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL) -- get sysarticles information select @dest_owner = dest_owner, @dest_tabname = dest_table, @src_objid = objid, @del_cmd = del_cmd from sysarticles where artid = @artid if @dest_owner is not null begin select @dest_owner = QUOTENAME( @dest_owner ) + N'.' end else begin select @dest_owner = N'' end -------- get dest proc name if( 1 != charindex( N'CALL', upper(@del_cmd) ) ) or @del_cmd is null begin raiserror (14156, 16, 1 ) return 1 end select @dest_proc = substring( @del_cmd, 6, len( @del_cmd ) - 4 ) select @cmd = N'create procedure ' + QUOTENAME(@dest_proc) -------- construct parameter list select @this_col = 1 select @art_col = 1 select @src_cols = count(*) from syscolumns where id = @src_objid select @spacer = N' ' exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1) begin if len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' end exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT select @cmd = @cmd + @spacer + N'@pkc' + convert( nvarchar, @art_col ) + N' ' + @typestring select @art_col = @art_col + 1 select @spacer = N',' end select @this_col = @this_col + 1 end -- save off insert into #proctext(procedure_text) values( @cmd ) insert into #proctext(procedure_text) values( N'as' ) ------- construct proc body insert into #proctext(procedure_text) values( N'delete ' + @dest_owner + QUOTENAME(@dest_tabname) ) exec dbo.sp_scriptpkwhereclause @src_objid, @src_cols, @pkcolumns -- flush to client select procedure_text from #proctext order by c1 asc go EXEC dbo.sp_MS_marksystemobject sp_scriptdelproc GO ---------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------- ---------------------------------------------------------------------------------------------- print '' print 'Creating procedure sp_scriptupdproc' go create procedure sp_scriptupdproc @artid int as declare @cmd nvarchar(4000) declare @dest_owner nvarchar(255) declare @dest_tabname sysname declare @src_objid int declare @artcolumns binary(32) declare @pkcolumns binary(32) declare @upd_cmd nvarchar(255) declare @dest_proc sysname declare @src_cols int declare @this_col int declare @art_col int declare @pkart_col int declare @isset int declare @typestring nvarchar(255) declare @spacer nvarchar(10) if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 ) begin raiserror (14155, 16, 1 ) return 1 end -------- create temp table for command fragments create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL) -------- get sysarticles information select @dest_owner = dest_owner, @dest_tabname = dest_table, @src_objid = objid, @artcolumns = columns, @upd_cmd = upd_cmd from sysarticles where artid = @artid if @dest_owner is not null begin select @dest_owner = QUOTENAME( @dest_owner ) + N'.' end else begin select @dest_owner = N'' end -------- get dest proc name if( 1 != charindex( N'CALL', upper(@upd_cmd) ) ) or @upd_cmd is null begin raiserror (14156, 16, 1 ) return 1 end select @dest_proc = substring( @upd_cmd, 6, len( @upd_cmd ) - 4 ) insert into #proctext( procedure_text ) values ( N'create procedure ' + QUOTENAME(@dest_proc) + N' ') -------- construct parameter list select @src_cols = count(*) from syscolumns where id = @src_objid exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output exec dbo.sp_scriptupdateparams @src_objid, @src_cols, @artcolumns, @pkcolumns insert into #proctext(procedure_text) values ( N'as' ) -------- now create the update statement -- construct test to see if pk has changed -- only do this if the article has columns not included in the pk if @artcolumns != @pkcolumns begin select @cmd = N'if' select @this_col = 1 select @art_col = 1 select @pkart_col = 1 select @spacer = ' ' while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1) begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns if @isset != 0 begin select @cmd = @cmd + @spacer + N'@c'+convert( nvarchar, @art_col ) + N' = @pkc' + convert( nvarchar, @pkart_col ) select @spacer = N' and ' select @pkart_col = @pkart_col + 1 if len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' end end select @art_col = @art_col + 1 end select @this_col = @this_col + 1 end insert into #proctext(procedure_text) values( @cmd ) -- construct update if pk hasn't changed select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set' -- create SET clause select @this_col = 1 select @art_col = 1 select @spacer = N' ' while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1) begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns if @isset = 0 begin select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = @c' + convert( nvarchar, @art_col ) select @spacer = N',' if len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' end end select @art_col = @art_col + 1 end select @this_col = @this_col + 1 end insert into #proctext(procedure_text) values( @cmd ) exec dbo.sp_scriptpkwhereclause @src_objid, @src_cols, @pkcolumns insert into #proctext(procedure_text) values( N'else' ) end -- end if artcols != pkcols -- construct update if pk has changed select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set' -- create SET clause select @this_col = 1 select @art_col = 1 select @spacer = N' ' while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1) begin select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = @c' + convert( nvarchar, @art_col ) select @art_col = @art_col + 1 select @spacer = N',' if len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' end end select @this_col = @this_col + 1 end insert into #proctext(procedure_text) values( @cmd ) exec dbo.sp_scriptpkwhereclause @src_objid, @src_cols, @pkcolumns -- flush to client select procedure_text from #proctext order by c1 asc go EXEC dbo.sp_MS_marksystemobject sp_scriptupdproc GO -------------------------------------------------------------------------- -------------------------------------------------------------------------- print '' print 'Creating procedure sp_scriptmappedupdproc' go create procedure sp_scriptmappedupdproc @artid int as declare @cmd nvarchar(4000) declare @dest_owner nvarchar(255) declare @dest_tabname sysname declare @src_objid int declare @artcolumns binary(32) declare @pkcolumns binary(32) declare @upd_cmd nvarchar(255) declare @dest_proc sysname declare @src_cols int declare @art_cols int declare @this_col int declare @art_col int declare @pkart_col int declare @isset int declare @bytestr nvarchar(10) declare @bitstr nvarchar(10) declare @typestring nvarchar(255) declare @spacer nvarchar(10) declare @exists_else bit select @exists_else = 0 if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 ) begin raiserror (14155, 16, 1 ) return 1 end -------- create temp table for command fragments create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) ) -------- get sysarticles information select @dest_owner = dest_owner, @dest_tabname = dest_table, @src_objid = objid, @artcolumns = columns, @upd_cmd = upd_cmd from sysarticles where artid = @artid if @dest_owner is not null begin select @dest_owner = QUOTENAME( @dest_owner ) + N'.' end else begin select @dest_owner = N'' end -------- get dest proc name if( 1 != charindex( N'MCALL', upper(@upd_cmd) ) ) or @upd_cmd is null begin raiserror (14156, 16, 1 ) return 1 end select @dest_proc = substring( @upd_cmd, 7, len( @upd_cmd ) - 5 ) insert into #proctext( procedure_text ) values ( N'create procedure ' + QUOTENAME(@dest_proc) + N' ' ) -------- construct parameter list select @src_cols = count(*) from syscolumns where id = @src_objid exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output exec dbo.sp_scriptupdateparams @src_objid, @src_cols, @artcolumns, @pkcolumns ----- add changed data bitmap select @this_col = 1 select @art_col = 1 while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid) begin select @art_col = @art_col + 1 end select @this_col = @this_col + 1 end -- Note that bitmap size is based on number of article columns -- (computed by loop above) not source table columns select @cmd = N',@bitmap binary(' + convert(nvarchar,1+(@art_col-1) / 8) + N')' insert into #proctext(procedure_text) values( @cmd ) insert into #proctext(procedure_text) values( N'as' ) -- construct IF statement -- do this only if the article contains columns not included in the pk if @artcolumns != @pkcolumns begin select @this_col = 1 select @art_col = 1 select @spacer = N' ' select @cmd = N'if' while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1) begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns if @isset != 0 begin select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 ) select @bitstr = convert( nvarchar, power(2, (@art_col-1) % 8 ) ) select @cmd = @cmd + @spacer + N'substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr + N' = ' + @bitstr select @spacer = N' or ' if len( @cmd ) > 3000 begin insert into #proctext(procedure_text) values( @cmd ) select @cmd = N'' end end select @art_col = @art_col + 1 end select @this_col = @this_col + 1 end insert into #proctext(procedure_text) values( @cmd ) end -- if artcolumns != pkcolumns -- construct update statement including PK columns insert into #proctext(procedure_text) values( N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set' ) -- create SET clause consisting of CASE statements select @this_col = 1 select @art_col = 1 select @spacer = N'' while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid) begin select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 ) select @bitstr = convert( nvarchar, power(2, (@art_col-1) % 8 ) ) insert into #proctext(procedure_text) values ( @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = case substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr + N' when ' + @bitstr + N' then ' + N'@c'+ convert( nvarchar, @art_col ) + N' else ' + QUOTENAME(col_name( @src_objid, @this_col)) + N' end' ) select @spacer = ',' select @art_col = @art_col + 1 end select @this_col = @this_col + 1 end -- create where clause exec dbo.sp_scriptpkwhereclause @src_objid, @src_cols, @pkcolumns -- construct UPDATE that does not set PK cols -- only do this if the article contains columns that are not included -- in the pk if @artcolumns != @pkcolumns begin -- create SET clause consisting of CASE statements select @this_col = 1 select @art_col = 1 select @spacer = N'' while @this_col <= @src_cols begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid) begin exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns if @isset = 0 begin if (@exists_else = 0) begin insert into #proctext(procedure_text) values( N'else' ) insert into #proctext(procedure_text) values( N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set' ) select @exists_else = 1 end select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 ) select @bitstr = convert( nvarchar, power(2, (@art_col-1) % 8 ) ) insert into #proctext(procedure_text) values ( @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = case substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr + N' when ' + @bitstr + N' then ' + N'@c'+ convert( nvarchar, @art_col ) + N' else ' + QUOTENAME(col_name( @src_objid, @this_col)) + N' end' ) select @spacer = ',' end select @art_col = @art_col + 1 end select @this_col = @this_col + 1 end if @exists_else=1 exec dbo.sp_scriptpkwhereclause @src_objid, @src_cols, @pkcolumns end select procedure_text from #proctext order by c1 asc go EXEC dbo.sp_MS_marksystemobject sp_scriptmappedupdproc GO -------------------------------------------------------------------------- -------------------------------------------------------------------------- print '' print 'Creating procedure sp_fetchshowcmdsinput' go create procedure sp_fetchshowcmdsinput @numcmds int as create table #rcmds( article_id int NOT NULL, partial_command int NOT NULL, command varbinary(1024) NULL, xactid binary(10) NOT NULL, xact_seqno binary(10) NOT NULL, publication_id int NOT NULL, command_id int NOT NULL, command_type int NOT NULL, originator_srvname nvarchar(128) NULL, originator_db nvarchar(128) NULL) insert into #rcmds exec dbo.sp_replcmds @numcmds select convert( varbinary(16), xact_seqno ), 0, 0, article_id, command_type, partial_command, command from #rcmds order by xact_seqno, article_id, command_id asc drop table #rcmds go EXEC dbo.sp_MS_marksystemobject sp_fetchshowcmdsinput GO -------------------------------------------------------------------------- -------------------------------------------------------------------------- print '' print 'Creating procedure sp_replshowcmds' go create procedure sp_replshowcmds @maxtrans int = 1 as declare @query nvarchar(1024) declare @dbname sysname select @dbname = db_name() select @query = 'execute dbo.sp_fetchshowcmdsinput ' + convert( nvarchar, @maxtrans ) execute master..xp_printstatements @query, @dbname go EXEC dbo.sp_MS_marksystemobject sp_replshowcmds GO print '' print 'Creating procedure sp_publication_validation' go create procedure sp_publication_validation @publication sysname, @rowcount_only bit = 1, @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 -- Set for last article in publication, which will signal subscriber synchronization agent to shutdown -- immediately after successful validation as set nocount on declare @publication_id int declare @article sysname declare @article2 sysname declare @retcode int declare @publish_bit int -- Security Check exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) set @publish_bit = 1 -- Check if the database is published for transactional if not exists (select * from master..sysdatabases where name = db_name() and (category & @publish_bit) = @publish_bit) begin raiserror(20026, 16, -1, @publication) return 1 end -- Get Publication Information select @publication_id = pubid from syspublications where name = @publication if @publication_id is null begin raiserror(20026, 16, -1, @publication) return 1 end declare hC CURSOR LOCAL FAST_FORWARD for select name from sysarticles where pubid = @publication_id and (status & 1) <> 0 -- active articles only open hC fetch hC into @article while (@@fetch_status <> -1) begin set @article2 = @article -- Look ahead to next article fetch hC into @article -- If we are at the last article, pass the @shutdown_agent value if (@@fetch_status = -1) begin exec @retcode = dbo.sp_article_validation @publication, @article2, @rowcount_only = @rowcount_only, @full_or_fast = @full_or_fast, @shutdown_agent = @shutdown_agent end else exec @retcode = dbo.sp_article_validation @publication, @article2, @rowcount_only = @rowcount_only, @full_or_fast = @full_or_fast if @retcode <> 0 or @@error <> 0 begin close hC deallocate hC return 1 end end close hC deallocate hC go EXEC dbo.sp_MS_marksystemobject sp_publication_validation GO print '' print 'Creating procedure sp_article_validation' go create procedure sp_article_validation @publication sysname, @article sysname, -- The following are values passed to the sp_table_validation call at the subscriber. @rowcount_only bit = 1, @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 subscriber synchronization agent to shutdown -- immediately after successful validation as declare @publication_guid uniqueidentifier declare @publication_id int declare @article_guid uniqueidentifier declare @article_id int declare @source_name sysname declare @destination_table sysname declare @destination_owner sysname declare @columns varbinary(32) declare @command varchar (4096) declare @retcode int declare @actual_rowcount int declare @actual_checksum numeric declare @status int declare @active int declare @vertical_partition bit declare @publish_bit int declare @table_name sysname -- base table name var to passed to sp_table_validation set nocount on -- Security Check exec @retcode = dbo.sp_MSreplcheck_publish if @@ERROR <> 0 or @retcode <> 0 return(1) set @active = 1 set @publish_bit = 1 -- Check if the database is published for transactional if not exists (select * from master..sysdatabases where name = db_name() and (category & @publish_bit) = @publish_bit) begin raiserror(20026, 16, -1, @publication) return 1 end -- Get Publication Information select @publication_id = pubid from syspublications where name = @publication if @publication_id is null begin raiserror(20026, 16, -1, @publication) return 1 end -- Get Article Information select @article_id = artid, @source_name = OBJECT_NAME(sync_objid), @destination_table = dest_table, @destination_owner = dest_owner, @status = status, @table_name = OBJECT_NAME(objid), @columns = columns from sysarticles where name = @article and pubid=@publication_id if @article_id is null begin raiserror(20027, 16, -1, @article) return 1 end -- Make sure article status is 'active' if (@status & @active) <> @active begin -- Article is not active raiserror(20523, 16, -1, @article) return 1 end -- Check if table has vertical partition if exists (select * from sysarticles a, syscolumns b where (CONVERT(bit, convert(binary(2), SUBSTRING(convert(nvarchar,a.columns), CONVERT(tinyint, 16 - FLOOR((colid-1)/16)), 1)) & POWER(2, ((colid-1)%16))) = 0 OR CONVERT(bit, convert(binary(2), SUBSTRING(convert( nvarchar,a.columns), CONVERT(tinyint, 16 - FLOOR((colid-1)/16)), 1)) & POWER(2, ((colid-1)%16))) IS NULL) AND a.objid = b.id AND a.name = @article AND a.pubid = @publication_id) begin set @vertical_partition = 1 -- partitions only support row count validation, override specified value set @rowcount_only = 1 end else set @vertical_partition = 0 begin tran -- The table validation and posting to the log MUST happen with a transaction -- Get publisher's rowcount and/or checksum for the article if @rowcount_only = 1 begin exec @retcode = dbo.sp_table_validation @table = @source_name, @expected_rowcount = @actual_rowcount OUTPUT, @rowcount_only = 1, @full_or_fast = 0, @table_name = @table_name -- always do full count at publisher if @retcode <> 0 or @@error <> 0 begin commit tran return 1 end end else -- get checksum begin exec @retcode = dbo.sp_table_validation @table = @source_name, @expected_rowcount = @actual_rowcount OUTPUT, @expected_checksum = @actual_checksum OUTPUT, @rowcount_only = 0, @full_or_fast = 0, @table_name = @table_name -- always do full count at publisher if @retcode <> 0 or @@error <> 0 begin commit tran return 1 end end -- Post sp_table_validation on behalf of the article and send to subscribers if @rowcount_only = 1 begin select @command = 'exec dbo.sp_table_validation @table = ''' + @destination_table + ''', @expected_rowcount = ' + convert(varchar(10), @actual_rowcount) + ', @rowcount_only = 1' + ', @full_or_fast = ' + convert(varchar(10), @full_or_fast) + ', @shutdown_agent = ' + convert(varchar(10), @shutdown_agent) end else begin select @command = 'exec dbo.sp_table_validation @table = ''' + @destination_table + ''', @expected_rowcount = ' + convert(varchar(10), @actual_rowcount) + ', @expected_checksum = ' + convert(varchar(100), @actual_checksum) + ', @rowcount_only = 0' + ', @full_or_fast = ' + convert(varchar(10), @full_or_fast) + ', @shutdown_agent = ' + convert(varchar(10), @shutdown_agent) end -- Add owner param if destination owner is not NULL if (@destination_owner IS NOT NULL) begin select @command = @command + ', @owner = ''' + @destination_owner + '''' end -- DEBUG select @command exec @retcode = dbo.sp_replpostcmd 0, -- partial flag @publication_id, @article_id, 35, -- SQL Server Only command type @command if @retcode <> 0 or @@error <> 0 begin commit tran return 1 end commit tran go EXEC dbo.sp_MS_marksystemobject sp_article_validation GO print '' print 'Creating procedure sp_MSdrop_6x_replication_agent' go create procedure sp_MSdrop_6x_replication_agent @job_id UNIQUEIDENTIFIER, @category_id int as declare @distbit int declare @db_name sysname declare @cmd varchar(4000) select @distbit = 16 declare hCdatabase CURSOR LOCAL FAST_FORWARD FOR select name from master.dbo.sysdatabases where category & @distbit <> 0 for read only open hCdatabase fetch next from hCdatabase into @db_name while (@@fetch_status <> -1) begin if @category_id = 13 begin select @cmd = 'delete from ' + @db_name + '.dbo.MSlogreader_agents where job_id = convert (uniqueidentifier, ''' + convert (varchar(100), @job_id) + ''')' exec (@cmd) end else if @category_id = 15 begin select @cmd = @db_name + '.dbo.sp_MSdrop_6x_publication' exec @cmd @job_id = @job_id end else return 0 if @@ERROR <> 0 return 1 fetch next from hCdatabase into @db_name end close hCdatabase deallocate hCdatabase go EXEC dbo.sp_MS_marksystemobject sp_MSdrop_6x_replication_agent GO --------------------------------------------------------------------------- --------------------------------------------------------------------------- grant execute on dbo.sp_enumfullsubscribers to public go grant execute on dbo.sp_addpublication to public go grant execute on dbo.sp_changepublication to public go grant execute on dbo.sp_changesubscription to public go grant execute on dbo.sp_articlecolumn to public go grant execute on dbo.sp_helparticle to public go grant execute on dbo.sp_helparticlecolumns to public go grant execute on dbo.sp_helppublication to public go grant execute on dbo.sp_publication_validation to public go grant execute on dbo.sp_article_validation to public go grant execute on dbo.sp_helpsubscription to public go grant execute on dbo.sp_articlefilter to public go grant execute on dbo.sp_articleview to public go grant execute on dbo.sp_addarticle to public go grant execute on dbo.sp_changesubstatus to public go grant execute on dbo.sp_addsubscription to public go grant execute on dbo.sp_changearticle to public go grant execute on dbo.sp_droparticle to public go grant execute on dbo.sp_droppublication to public go grant execute on dbo.sp_dropsubscription to public go grant execute on dbo.sp_subscribe to public go grant execute on dbo.sp_unsubscribe to public go grant execute on dbo.sp_refreshsubscriptions to public go grant execute on dbo.sp_reinitsubscription to public go -- SyncTran grant exec on dbo.sp_articlesynctranprocs to public go -- custom proc gen. grant exec on dbo.sp_getarticlepkcolbitmap to public go grant exec on dbo.sp_gettypestring to public go grant exec on dbo.sp_isarticlecolbitset to public go grant exec on dbo.sp_scriptpkwhereclause to public go grant exec on dbo.sp_scriptupdateparams to public go grant exec on dbo.sp_scriptinsproc to public go grant exec on dbo.sp_scriptdelproc to public go grant exec on dbo.sp_scriptupdproc to public go grant exec on dbo.sp_scriptmappedupdproc to public go grant exec on dbo.sp_script_synctran_commands to public go grant exec on dbo.sp_MSget_synctran_commands to public go grant exec on dbo.sp_MSactivate_auto_sub to public go grant execute on dbo.sp_MSscript_insert_statement to public grant execute on dbo.sp_MSscript_update_statement to public grant execute on dbo.sp_MSscript_delete_statement to public grant execute on dbo.sp_MSscript_beginproc to public grant execute on dbo.sp_MSscript_security to public grant execute on dbo.sp_MSscript_endproc to public grant execute on dbo.sp_MSscript_sync_ins_proc to public grant execute on dbo.sp_MSscript_sync_upd_proc to public grant execute on dbo.sp_MSscript_sync_del_proc to public grant execute on dbo.sp_MSmark_proc_norepl 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 repltran.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 'repltran.sql completed successfully.' go dump tran master with no_log go checkpoint go -- - -----