home *** CD-ROM | disk | FTP | other *** search
/ Chip 2003 October / Chip Ekim 2003.iso / prog / tamsurum / tocom / Security Updates / SQL-MSDE-CriticalUpdate_ENU.msi / Hotfix3 / Files / repltran.sql < prev    next >
Encoding:
Text File  |  2001-10-03  |  860.6 KB  |  28,163 lines

  1. /*
  2. ** repltran.sql            1997/02/12 22:03
  3. **
  4. **
  5. ** Copyright Microsoft, Inc. 1998-2000
  6. ** All Rights Reserved.
  7. */
  8.  
  9.  
  10. use master
  11. go
  12.  
  13. dump tran master with no_log
  14. go
  15.  
  16. exec dbo.sp_configure 'update',1
  17. go
  18. reconfigure with override
  19. go
  20.  
  21. set ANSI_NULLS off
  22. go
  23.  
  24. -- sp_MS_upd_sysobj_category is obsolete, use sp_MS_marksystemobject instead
  25. -- exec dbo.sp_MS_upd_sysobj_category 1 --Capture time for use at the end
  26. -- go
  27.  
  28. if exists (select * from sysobjects
  29.     where type = 'P '
  30.             and name = 'sp_MSdrop_repltran')
  31. begin
  32.     drop procedure sp_MSdrop_repltran
  33. end
  34.  
  35. /*
  36. ** Create stored procedures to drop the stored procedures
  37. ** created by this script
  38. */
  39.  
  40.  
  41. print ''
  42. print 'Creating procedure sp_MSdrop_repl_tran.'
  43. go
  44. create procedure sp_MSdrop_repltran
  45. as
  46.  
  47.     if exists( select * from sysobjects 
  48.         where type = 'P '
  49.             and name = 'sp_MSsetfilterparent' )
  50.         drop procedure sp_MSsetfilterparent
  51.  
  52.     if exists( select * from sysobjects 
  53.         where type = 'P '
  54.             and name = 'sp_MSdoesfilterhaveparent' )
  55.         drop procedure sp_MSdoesfilterhaveparent
  56.  
  57.     if exists( select * from sysobjects 
  58.         where type = 'P '
  59.             and name = 'sp_MSsetfilteredstatus' )
  60.         drop procedure sp_MSsetfilteredstatus
  61.  
  62.     if exists ( select * from sysobjects 
  63.         where type = 'P '
  64.             and name = 'sp_MSreplsup_table_has_pk' )
  65.         DROP PROC sp_MSreplsup_table_has_pk
  66.  
  67.     if exists (select * from sysobjects
  68.         where type = 'P '
  69.                 and name = 'sp_MScreate_pub_tables')
  70.         drop procedure sp_MScreate_pub_tables
  71.  
  72.     if exists (select * from sysobjects
  73.         where type = 'P '
  74.                 and name = 'sp_MSdrop_expired_subscription')
  75.         drop procedure sp_MSdrop_expired_subscription
  76.     
  77.     if exists (select * from sysobjects
  78.             where type = 'P '
  79.                 and name = 'sp_replsync')
  80.         drop procedure sp_replsync
  81.  
  82.     if exists (select * from sysobjects
  83.             where type = 'P '
  84.                 and name = 'sp_enumfullsubscribers')
  85.         drop procedure sp_enumfullsubscribers
  86.     
  87.     if exists (select * from sysobjects
  88.         where type = 'P '
  89.                 and name = 'sp_MSaddexecarticle')
  90.         drop procedure sp_MSaddexecarticle
  91.     
  92.  
  93.     dump tran master with no_log
  94.     
  95.  
  96.     if exists (select * from sysobjects
  97.             where type = 'P '
  98.                 and name = 'sp_addarticle')
  99.         drop procedure sp_addarticle
  100.     
  101.     if exists (select * from sysobjects
  102.             where type = 'P '
  103.                 and name = 'sp_MSaddschemaarticle')
  104.         drop procedure sp_MSaddschemaarticle
  105.  
  106.     if exists (select * from sysobjects
  107.             where type = 'P '
  108.                 and name = 'sp_MSchangeschemaarticle')
  109.         drop procedure sp_MSchangeschemaarticle
  110.  
  111.     if exists (select * from sysobjects
  112.             where type = 'P '
  113.                 and name = 'sp_MSgettranconflictname')
  114.         drop procedure sp_MSgettranconflictname    
  115.  
  116.     if exists (select * from sysobjects
  117.             where type = 'P '
  118.                 and name = 'sp_MSretrieve_publication')
  119.         drop procedure sp_MSretrieve_publication    
  120.  
  121.     if exists (select * from sysobjects
  122.             where type = 'P '
  123.                 and name = 'sp_MSmaketrancftproc')
  124.         drop procedure sp_MSmaketrancftproc    
  125.  
  126.     if exists (select * from sysobjects
  127.         where type = 'P '
  128.                 and name = 'sp_articlecolumn')
  129.         drop procedure sp_articlecolumn
  130.     
  131.     dump tran master with no_log
  132.     
  133.  
  134.     if exists (select * from sysobjects
  135.             where type = 'P '
  136.                 and name = 'sp_articlefilter')
  137.         drop procedure sp_articlefilter
  138.        
  139.  
  140.  
  141.     if exists (select * from sysobjects
  142.         where type = 'P '
  143.                 and name = 'sp_MSarticlecol')
  144.         drop procedure sp_MSarticlecol
  145.     
  146.  
  147.     dump tran master with no_log
  148.     
  149.  
  150.     if exists (select * from sysobjects
  151.         where type = 'P '
  152.                 and name = 'sp_MSarticlecolstatus')
  153.         drop procedure sp_MSarticlecolstatus
  154.     
  155.     if exists (select * from sysobjects
  156.             where type = 'P '
  157.                 and name = 'sp_MSscript_article_view')
  158.         drop procedure sp_MSscript_article_view 
  159.  
  160.     if exists (select * from sysobjects
  161.             where type = 'P '
  162.                 and name = 'sp_articleview')
  163.         drop procedure sp_articleview
  164.     
  165.  
  166.     dump tran master with no_log
  167.     
  168.  
  169.     if exists (select * from sysobjects
  170.             where type = 'P '
  171.                 and name = 'sp_addpublication')
  172.         drop procedure sp_addpublication
  173.     
  174.  
  175.     dump tran master with no_log
  176.     
  177.  
  178.     if exists (select * from sysobjects
  179.             where type = 'P '
  180.                 and name = 'sp_addsubscription')
  181.         drop procedure sp_addsubscription
  182.     
  183.  
  184.     IF EXISTS (SELECT * FROM sysobjects
  185.             WHERE type = 'P '
  186.                 AND name = 'sp_changearticle')
  187.         DROP PROCEDURE sp_changearticle
  188.     
  189.  
  190.     dump tran master with no_log
  191.     
  192.  
  193.     IF EXISTS (SELECT * FROM sysobjects
  194.             WHERE type = 'P '
  195.                 AND name = 'sp_changepublication')
  196.         DROP PROCEDURE sp_changepublication
  197.     
  198.  
  199.  
  200.     IF EXISTS (SELECT * FROM sysobjects
  201.             WHERE type = 'P '
  202.                 AND name = 'sp_changesubscription')
  203.         DROP PROCEDURE sp_changesubscription
  204.     
  205.  
  206.     dump tran master with no_log
  207.     
  208.  
  209.     if exists (select * from sysobjects
  210.             where type = 'P '
  211.                 and name = 'sp_MShcchangesubstatus1')
  212.         drop procedure sp_MShcchangesubstatus1
  213.     
  214.  
  215.     if exists (select * from sysobjects
  216.             where type = 'P '
  217.                 and name = 'sp_MShcchangesubstatus2')
  218.         drop procedure sp_MShcchangesubstatus2
  219.     
  220.  
  221.     if exists (select * from sysobjects
  222.             where type = 'P '
  223.                 and name = 'sp_MShcchangesubstatus3')
  224.         drop procedure sp_MShcchangesubstatus3
  225.     
  226.  
  227.     dump tran master with no_log
  228.     
  229.  
  230.     if exists (select * from sysobjects
  231.             where type = 'P '
  232.                 and name = 'sp_changesubstatus')
  233.         drop procedure sp_changesubstatus
  234.     
  235.  
  236.     if exists (select * from sysobjects
  237.             where type = 'P '
  238.                 and name = 'sp_droparticle')
  239.         drop procedure sp_droparticle
  240.     
  241.  
  242.     dump tran master with no_log
  243.     
  244.  
  245.     if exists (select * from sysobjects
  246.             where type = 'P '
  247.                 and name = 'sp_droppublication')
  248.         drop procedure sp_droppublication
  249.     
  250.  
  251.     if exists (select * from sysobjects
  252.             where type = 'P '
  253.                 and name = 'sp_dropsubscription')
  254.         drop procedure sp_dropsubscription
  255.     
  256.  
  257.     dump tran master with no_log
  258.     
  259.  
  260.     if exists (select * from sysobjects
  261.             where type = 'P '
  262.                 and name = 'sp_helparticle')
  263.         drop procedure sp_helparticle
  264.     
  265.  
  266.     dump tran master with no_log
  267.     
  268.  
  269.     if exists (select * from sysobjects
  270.             where type = 'P '
  271.                 and name = 'sp_helparticlecolumns')
  272.         drop procedure sp_helparticlecolumns
  273.     
  274.  
  275.     if exists (select * from sysobjects
  276.             where type = 'P '
  277.                 and name = 'sp_helppublication')
  278.         drop procedure sp_helppublication
  279.     
  280.         
  281.     if exists (select * from sysobjects
  282.             where type = 'P '
  283.                 and name = 'sp_MSaddpub_snapshot')
  284.         drop procedure sp_MSaddpub_snapshot
  285.  
  286.     dump tran master with no_log
  287.     
  288.  
  289.     if exists (select * from sysobjects
  290.             where type = 'P '
  291.                 and name = 'sp_helpsubscription')
  292.         drop procedure sp_helpsubscription
  293.     
  294.  
  295.     if exists (select * from sysobjects
  296.             where type = 'P '
  297.                 and name = 'sp_subscribe')
  298.         drop procedure sp_subscribe
  299.     
  300.  
  301.     if exists (select * from sysobjects
  302.             where type = 'P '
  303.                 and name = 'sp_unsubscribe')
  304.         drop procedure sp_unsubscribe
  305.     
  306.  
  307.     if exists (select * from sysobjects
  308.             where type = 'P '
  309.                 and name = 'sp_refreshsubscriptions')
  310.         drop procedure sp_refreshsubscriptions
  311.     
  312.  
  313.     dump tran master with no_log
  314.     
  315.  
  316.     if exists (select * from sysobjects
  317.             where type = 'P '
  318.                 and name = 'sp_MSpublishdb')
  319.         drop procedure sp_MSpublishdb
  320.     
  321.  
  322.     if exists (select * from sysobjects
  323.             where type = 'P '
  324.                 and name = 'sp_MSactivate_auto_sub')
  325.         drop procedure sp_MSactivate_auto_sub
  326.     
  327.  
  328.     if exists (select * from sysobjects
  329.             where type = 'P '
  330.                 and name = 'sp_MSget_synctran_commands')
  331.         drop procedure sp_MSget_synctran_commands
  332.  
  333.  
  334.     if exists (select * from sysobjects
  335.         where type = 'P '
  336.                 and name = 'sp_MSdrop_pub_tables')
  337.     begin
  338.         -- Don't drop the system tables here. repltran.sql should not
  339.         -- delete any data in the master database.
  340.         -- exec dbo.sp_MSdrop_pub_tables
  341.         drop procedure sp_MSdrop_pub_tables
  342.     end
  343.  
  344.     -- SyncTran
  345.     if exists (select * from sysobjects
  346.         where type = 'P '
  347.                 and name = 'sp_MSis_col_replicated')
  348.         drop procedure  sp_MSis_col_replicated
  349.  
  350.     if exists (select * from sysobjects
  351.         where type = 'P '
  352.                 and name = 'sp_MSis_pk_col')
  353.         drop procedure  sp_MSis_pk_col
  354.  
  355.    if exists (select * from sysobjects
  356.         where type = 'P '
  357.                 and name = 'sp_MSscript_compensating_send')
  358.         drop procedure sp_MSscript_compensating_send 
  359.  
  360.    if exists (select * from sysobjects
  361.         where type = 'P '
  362.                 and name = 'sp_MSscript_insert_statement')
  363.         drop procedure sp_MSscript_insert_statement 
  364.  
  365.    if exists (select * from sysobjects
  366.         where type = 'P '
  367.                 and name = 'sp_MSscript_insert_subwins')
  368.         drop procedure sp_MSscript_insert_subwins 
  369.  
  370.    if exists (select * from sysobjects
  371.         where type = 'P '
  372.                 and name = 'sp_MSscript_insert_pubwins')
  373.         drop procedure sp_MSscript_insert_pubwins 
  374.  
  375.    if exists (select * from sysobjects
  376.         where type = 'P '
  377.                 and name = 'sp_MSscript_validate_subscription')
  378.         drop procedure sp_MSscript_validate_subscription 
  379.  
  380.    if exists (select * from sysobjects
  381.         where type = 'P '
  382.                 and name = 'sp_MSvalidate_subscription')
  383.         drop procedure sp_MSvalidate_subscription 
  384.  
  385.    if exists (select * from sysobjects
  386.         where type = 'P '
  387.                 and name = 'sp_MSscript_update_statement')
  388.         drop procedure sp_MSscript_update_statement
  389.  
  390.    if exists (select * from sysobjects
  391.         where type = 'P '
  392.                 and name = 'sp_MSscript_update_subwins')
  393.         drop procedure sp_MSscript_update_subwins 
  394.  
  395.    if exists (select * from sysobjects
  396.         where type = 'P '
  397.                 and name = 'sp_MSscript_update_pubwins')
  398.         drop procedure sp_MSscript_update_pubwins 
  399.  
  400.    if exists (select * from sysobjects
  401.         where type = 'P '
  402.                 and name = 'sp_MSscript_delete_statement')
  403.         drop procedure sp_MSscript_delete_statement
  404.  
  405.    if exists (select * from sysobjects
  406.         where type = 'P '
  407.                 and name = 'sp_MSscript_delete_subwins')
  408.         drop procedure sp_MSscript_delete_subwins 
  409.  
  410.    if exists (select * from sysobjects
  411.         where type = 'P '
  412.                 and name = 'sp_MSscript_compensating_insert')
  413.         drop procedure sp_MSscript_compensating_insert 
  414.  
  415.    if exists (select * from sysobjects
  416.         where type = 'P '
  417.                 and name = 'sp_MSscript_delete_pubwins')
  418.         drop procedure sp_MSscript_delete_pubwins 
  419.  
  420.    if exists (select * from sysobjects
  421.         where type = 'P '
  422.                 and name = 'sp_MSscript_beginproc')
  423.         drop procedure sp_MSscript_beginproc
  424.  
  425.    if exists (select * from sysobjects
  426.         where type = 'P '
  427.                 and name = 'sp_MSscript_security')
  428.         drop procedure sp_MSscript_security
  429.  
  430.    if exists (select * from sysobjects
  431.         where type = 'P '
  432.                 and name = 'sp_MSscript_endproc')
  433.         drop procedure sp_MSscript_endproc
  434.  
  435.   if exists (select * from sysobjects
  436.         where type = 'P '
  437.                 and name = 'sp_MStable_not_modifiable')
  438.         drop procedure sp_MStable_not_modifiable
  439.  
  440.     if exists (select * from sysobjects
  441.         where type = 'P '
  442.                 and name = 'sp_MSscript_ExecutionMode_stmt')
  443.         drop procedure sp_MSscript_ExecutionMode_stmt
  444.  
  445.     if exists (select * from sysobjects
  446.         where type = 'P '
  447.                 and name = 'sp_MSscript_sync_ins_proc')
  448.         drop procedure sp_MSscript_sync_ins_proc
  449.  
  450.    if exists (select * from sysobjects
  451.         where type = 'P '
  452.                 and name = 'sp_MSscript_sync_upd_proc')
  453.         drop procedure sp_MSscript_sync_upd_proc 
  454.  
  455.    if exists (select * from sysobjects
  456.         where type = 'P '
  457.                 and name = 'sp_MSscript_sync_del_proc')
  458.         drop procedure sp_MSscript_sync_del_proc
  459.  
  460.    if exists (select * from sysobjects
  461.         where type = 'P '
  462.                 and name = 'sp_MSscript_pub_upd_trig')
  463.         drop procedure sp_MSscript_pub_upd_trig
  464.  
  465.    if exists (select * from sysobjects
  466.         where type = 'P '
  467.                 and name = 'sp_MSmakeconflicttable')
  468.         drop procedure sp_MSmakeconflicttable 
  469.  
  470.    if exists (select * from sysobjects
  471.         where type = 'P '
  472.                 and name = 'sp_scriptsubconflicttable')
  473.         drop procedure sp_scriptsubconflicttable 
  474.  
  475.    if exists (select * from sysobjects
  476.         where type = 'P '
  477.                 and name = 'sp_MSgen_sync_tran_procs')
  478.         drop procedure sp_MSgen_sync_tran_procs 
  479.  
  480.    if exists (select * from sysobjects
  481.         where type = 'P '
  482.                 and name = 'sp_MSis_identity_insert')
  483.         drop procedure sp_MSis_identity_insert 
  484.  
  485.     if exists (select * from sysobjects
  486.         where type = 'P '
  487.                 and name = 'sp_MSmark_proc_norepl')
  488.         drop procedure sp_MSmark_proc_norepl 
  489.  
  490.     if exists (select * from sysobjects
  491.         where type = 'P '
  492.                 and name = 'sp_articlesynctranprocs')
  493.         drop procedure sp_articlesynctranprocs
  494.  
  495.     if exists (select * from sysobjects
  496.         where type = 'P '
  497.                 and name = 'sp_reinitsubscription')
  498.         drop procedure sp_reinitsubscription
  499.  
  500.     dump tran master with no_log
  501.  
  502.     if exists( select * from sysobjects 
  503.         where type = 'P ' and name = N'sp_MSareallcolumnscomputed')
  504.     begin
  505.         drop procedure sp_MSareallcolumnscomputed
  506.     end
  507.  
  508.     if exists( select * from sysobjects 
  509.         where type = 'P ' and name = N'sp_gettypestring' )
  510.     begin
  511.         drop procedure sp_gettypestring
  512.     end
  513.  
  514.     if exists( select * from sysobjects 
  515.         where type = 'P ' and name = N'sp_MSgettypestringudt' )
  516.     begin
  517.         drop procedure sp_MSgettypestringudt
  518.     end
  519.  
  520.     if exists( select * from sysobjects 
  521.         where type = 'P ' and name = N'sp_scriptpkwhereclause' )
  522.     begin
  523.         drop procedure sp_scriptpkwhereclause
  524.     end
  525.  
  526.     if exists( select * from sysobjects 
  527.         where type = 'P ' and name = N'sp_MSscript_missing_row_check' )
  528.     begin
  529.         drop procedure sp_MSscript_missing_row_check
  530.     end
  531.  
  532.     if exists( select * from sysobjects 
  533.         where type = 'P ' and name = N'sp_scriptupdateparams' )
  534.     begin
  535.         drop procedure sp_scriptupdateparams
  536.     end
  537.  
  538.     if exists( select * from sysobjects 
  539.         where type = 'P ' and name = N'sp_scriptreconwhereclause' )
  540.     begin
  541.         drop procedure sp_scriptreconwhereclause
  542.     end
  543.  
  544.     if exists( select * from sysobjects 
  545.         where type = 'P ' and name = N'sp_script_reconciliation_insproc' )
  546.     begin
  547.         drop procedure sp_script_reconciliation_insproc
  548.     end
  549.  
  550.     if exists( select * from sysobjects 
  551.         where type = 'P ' and name = N'sp_script_reconciliation_delproc' )
  552.     begin
  553.         drop procedure sp_script_reconciliation_delproc
  554.     end
  555.  
  556.     if exists( select * from sysobjects 
  557.         where type = 'P ' and name = N'sp_script_reconciliation_xdelproc' )
  558.     begin
  559.         drop procedure sp_script_reconciliation_xdelproc
  560.     end
  561.  
  562.     if exists( select * from sysobjects 
  563.         where type = 'P ' and name = N'sp_scriptinsproc' )
  564.     begin
  565.         drop procedure sp_scriptinsproc
  566.     end
  567.  
  568.     if exists( select * from sysobjects 
  569.         where type = 'P ' and name = N'sp_scriptdelproc' )
  570.     begin
  571.         drop procedure sp_scriptdelproc
  572.     end
  573.  
  574.     if exists( select * from sysobjects 
  575.         where type = 'P ' and name = N'sp_scriptxdelproc' )
  576.     begin
  577.         drop procedure sp_scriptxdelproc
  578.     end
  579.  
  580.     if exists( select * from sysobjects 
  581.         where type = 'P ' and name = N'sp_scriptupdproc' )
  582.     begin
  583.         drop procedure sp_scriptupdproc
  584.     end
  585.  
  586.     if exists( select * from sysobjects 
  587.         where type = 'P ' and name = N'sp_scriptxupdproc' )
  588.     begin
  589.         drop procedure sp_scriptxupdproc
  590.     end
  591.  
  592.     if exists ( select * from sysobjects 
  593.         where type = 'P ' and name = 'sp_scriptmappedupdproc' )
  594.     begin
  595.         drop procedure sp_scriptmappedupdproc
  596.     end
  597.  
  598.     if exists ( select * from sysobjects 
  599.         where type = 'P ' and name = 'sp_scriptdynamicupdproc' )
  600.     begin
  601.         drop procedure sp_scriptdynamicupdproc
  602.     end
  603.  
  604.     if exists ( select * from sysobjects 
  605.         where type = 'P ' and name = 'sp_MSscriptmvastablenci' )
  606.     begin
  607.         drop procedure sp_MSscriptmvastablenci
  608.     end
  609.  
  610.     if exists ( select * from sysobjects 
  611.         where type = 'P ' and name = 'sp_MSscriptmvastablepkc' )
  612.     begin
  613.         drop procedure sp_MSscriptmvastablepkc
  614.     end
  615.  
  616.     if exists ( select * from sysobjects 
  617.         where type = 'P ' and name = 'sp_MSscriptmvastableidx' )
  618.     begin
  619.         drop procedure sp_MSscriptmvastableidx
  620.     end
  621.  
  622.     if exists ( select * from sysobjects 
  623.         where type = 'P ' and name = 'sp_MSscriptmvastable' )
  624.     begin
  625.         drop procedure sp_MSscriptmvastable
  626.     end
  627.  
  628.     if exists ( select * from sysobjects 
  629.         where type = 'P ' and name = 'sp_fetchshowcmdsinput' )
  630.     begin
  631.         drop procedure sp_fetchshowcmdsinput
  632.     end
  633.  
  634.     if exists ( select * from sysobjects 
  635.         where type = 'P ' and name = 'sp_replshowcmds' )
  636.     begin
  637.         drop procedure sp_replshowcmds
  638.     end
  639.  
  640.     if exists ( select * from sysobjects 
  641.         where type = 'P ' and name = 'sp_publication_validation' )
  642.     begin
  643.         drop procedure sp_publication_validation
  644.     end
  645.  
  646.     if exists ( select * from sysobjects 
  647.         where type = 'P ' and name = 'sp_marksubscriptionvalidation' )
  648.     begin
  649.         drop procedure sp_marksubscriptionvalidation
  650.     end
  651.  
  652.     if exists ( select * from sysobjects 
  653.         where type = 'P ' and name = 'sp_article_validation' )
  654.     begin
  655.         drop procedure sp_article_validation
  656.     end
  657.  
  658.     if exists ( select * from sysobjects 
  659.         where type = 'P ' and name = 'sp_MSdrop_6x_replication_agent' )
  660.     begin
  661.         drop procedure sp_MSdrop_6x_replication_agent
  662.     end
  663.  
  664.     if exists ( select * from sysobjects 
  665.         where type = 'P ' and name = 'sp_MSget_article_column_list' )
  666.     begin
  667.         drop procedure sp_MSget_article_column_list
  668.     end
  669.  
  670.     if exists ( select * from sysobjects 
  671.         where type = 'P ' and name = 'sp_MSpub_adjust_identity' )
  672.     begin
  673.         drop procedure sp_MSpub_adjust_identity
  674.     end
  675.  
  676.     if exists ( select * from sysobjects 
  677.         where type = 'P ' and name = 'sp_helparticledts' )
  678.     begin
  679.         drop procedure sp_helparticledts
  680.     end
  681.  
  682.     if exists ( select * from sysobjects 
  683.         where type = 'P ' and name = 'sp_changesubscriptiondtsinfo' )
  684.     begin
  685.         drop procedure sp_changesubscriptiondtsinfo
  686.     end
  687.  
  688.     if exists ( select * from sysobjects 
  689.         where type = 'P ' and name = 'sp_script_synctran_commands' )
  690.     begin
  691.         drop procedure sp_script_synctran_commands
  692.     end
  693.  
  694.     if exists ( select * from sysobjects 
  695.         where type = 'P ' and name = 'sp_MScomputearticlescreationorder' )
  696.     begin
  697.         drop procedure sp_MScomputearticlescreationorder
  698.     end
  699.  
  700.     if exists ( select * from sysobjects 
  701.         where type = 'P ' and name = 'sp_MScomputeunresolvedrefs' )
  702.     begin
  703.         drop procedure sp_MScomputeunresolvedrefs
  704.     end
  705.  
  706.     if exists ( select * from sysobjects 
  707.             where type = 'P ' and name = 'sp_MShelptranconflictpublications' )
  708.         drop procedure sp_MShelptranconflictpublications
  709.  
  710.     if exists ( select * from sysobjects 
  711.             where type = 'P ' and name = 'sp_MShelptranconflictcounts' )
  712.         drop procedure sp_MShelptranconflictcounts
  713.  
  714.     if exists ( select * from sysobjects 
  715.             where type = 'P ' and name = 'sp_MSgettranconflictrow' )
  716.         drop procedure sp_MSgettranconflictrow
  717.  
  718.     if exists ( select * from sysobjects 
  719.             where type = 'P ' and name = 'sp_MSgettrancftsrcrow' )
  720.         drop procedure sp_MSgettrancftsrcrow
  721.  
  722.     if exists ( select * from sysobjects 
  723.             where type = 'P ' and name = 'sp_MSdeletetranconflictrow' )
  724.         drop procedure sp_MSdeletetranconflictrow
  725.  
  726.     if exists ( select * from sysobjects
  727.             where type = 'P ' and name = 'sp_MSexternalfkreferences' )
  728.         drop procedure sp_MSexternalfkreferences    
  729.  
  730.     if exists ( select * from sysobjects
  731.             where type = 'P ' and name = 'sp_MSgetarticlereinitvalue' )
  732.         drop procedure sp_MSgetarticlereinitvalue    
  733.  
  734.     if exists ( select * from sysobjects
  735.             where type = 'P ' and name = 'sp_MSispkupdateinconflict' )
  736.         drop procedure sp_MSispkupdateinconflict    
  737.  
  738.     if exists ( select * from sysobjects
  739.             where type = 'P ' and name = 'sp_dropanonymousagent' )
  740.         drop procedure sp_dropanonymousagent    
  741.  
  742.     if exists ( select * from sysobjects
  743.             where type = 'P ' and name = 'sp_ivindexhasnullcols' )
  744.         drop procedure sp_ivindexhasnullcols    
  745.  
  746.     if exists (select * from sysobjects
  747.             where type = 'FN' and name = 'fn_sqlvarbasetostr')
  748.          drop function fn_sqlvarbasetostr
  749.  
  750.     if exists ( select * from sysobjects
  751.             where type = 'P ' and name = 'sp_replrestart' )
  752.         drop procedure sp_replrestart    
  753.  
  754.     if exists ( select * from sysobjects
  755.             where type = 'P ' and name = 'sp_MSreinit_article' )
  756.         drop procedure sp_MSreinit_article    
  757.  
  758.     if exists ( select * from sysobjects
  759.             where type = 'P ' and name = 'sp_replqueuemonitor' )
  760.         drop procedure sp_replqueuemonitor    
  761.  
  762.     if exists ( select * from sysobjects
  763.             where type = 'P ' and name = 'sp_replsqlqgetrows' )
  764.         drop procedure sp_replsqlqgetrows
  765.  
  766.     if exists ( select * from sysobjects
  767.             where type = 'P ' and name = 'sp_MSrepl_schema' )
  768.         drop procedure sp_MSrepl_schema    
  769.  
  770.     if exists ( select * from sysobjects
  771.             where type = 'P ' and name = 'sp_MSpost_auto_proc' )
  772.         drop procedure sp_MSpost_auto_proc    
  773.  
  774.     if exists ( select * from sysobjects
  775.             where type = 'P ' and name = 'sp_MSreplupdateschema' )
  776.         drop procedure sp_MSreplupdateschema    
  777.  
  778.     if exists ( select * from sysobjects
  779.             where type = 'P ' and name = 'sp_MSdefer_check' )
  780.         drop procedure sp_MSdefer_check    
  781.  
  782.     if exists ( select * from sysobjects
  783.             where type = 'P ' and name = 'sp_MSreenable_check' )
  784.         drop procedure sp_MSreenable_check    
  785.  
  786.     if exists ( select * from sysobjects
  787.             where type = 'P ' and name = 'sp_getqueuedrows' )
  788.         drop procedure sp_getqueuedrows    
  789.  
  790.     if exists ( select * from sysobjects
  791.             where type = 'P ' and name = 'sp_MSprep_exclusive' )
  792.         drop procedure sp_MSprep_exclusive    
  793.  
  794.     if exists ( select * from sysobjects
  795.         where type = 'P ' and name = 'sp_verify_publication' )
  796.     drop procedure sp_verify_publication
  797.  
  798.     if exists ( select * from sysobjects
  799.         where type = 'P ' and name = 'sp_scriptpublicationcustomprocs')
  800.     drop procedure sp_scriptpublicationcustomprocs
  801.  
  802.     dump tran master with no_log
  803. go
  804.  
  805. EXEC dbo.sp_MS_marksystemobject sp_MSdrop_repltran
  806. GO
  807.  
  808. EXEC dbo.sp_MSdrop_repltran
  809. GO
  810.  
  811. /* Create and execute dbo.sp_MSdrop_pub_tables */
  812.  
  813. print ''
  814. print 'Creating procedure sp_MSdrop_pub_tables'
  815. go
  816. CREATE PROCEDURE sp_MSdrop_pub_tables
  817. AS
  818.         
  819.     begin tran
  820.     save TRAN sp_drop_central_pub_tables
  821.     
  822.     /* drop 'sysarticles' */
  823.     IF exists (select * from sysobjects where name = 'sysarticles')
  824.     BEGIN
  825.         DROP TABLE sysarticles
  826.         IF @@ERROR <> 0
  827.         BEGIN
  828.             if @@trancount > 0
  829.             begin
  830.                 ROLLBACK TRAN sp_drop_central_pub_tables
  831.                 commit tran
  832.             end
  833.             RETURN(1)
  834.         END
  835.     END
  836.  
  837.     /* drop 'sysschemaarticles' */
  838.     IF exists (select * from sysobjects where name = 'sysschemaarticles')
  839.     BEGIN
  840.         DROP TABLE sysschemaarticles
  841.         IF @@ERROR <> 0
  842.         BEGIN
  843.             if @@trancount > 0
  844.             begin
  845.                 ROLLBACK TRAN sp_drop_central_pub_tables
  846.                 commit tran
  847.             end
  848.             RETURN (1)
  849.         END
  850.     END
  851.  
  852.     /* drop 'sysextendedarticlesview' */
  853.     IF exists (select * from sysobjects where name = 'sysextendedarticlesview')
  854.     BEGIN
  855.         DROP VIEW sysextendedarticlesview
  856.         IF @@ERROR <> 0
  857.         BEGIN
  858.             if @@trancount > 0
  859.             begin
  860.                 ROLLBACK TRAN sp_drop_central_pub_tables
  861.                 commit tran
  862.             end
  863.             RETURN (1)
  864.         END
  865.     END
  866.  
  867.  
  868.     /* drop 'syspublications' */
  869.     IF exists (select * from sysobjects where name = 'syspublications')
  870.     BEGIN
  871.         DROP TABLE syspublications
  872.         IF @@ERROR <> 0
  873.         BEGIN
  874.             if @@trancount > 0
  875.             begin
  876.                 ROLLBACK TRAN sp_drop_central_pub_tables
  877.                 commit tran
  878.             end
  879.             RETURN(1)
  880.         END
  881.     END
  882.  
  883.     /* drop 'syssubscriptions' */
  884.     IF exists (select * from sysobjects where name = 'syssubscriptions')
  885.     BEGIN
  886.         DROP TABLE syssubscriptions
  887.         IF @@ERROR <> 0
  888.         BEGIN
  889.             if @@trancount > 0
  890.             begin
  891.                 ROLLBACK TRAN sp_drop_central_pub_tables
  892.                 commit tran
  893.             end
  894.             RETURN(1)
  895.         END
  896.     END
  897.  
  898.     -- SyncTran
  899.     /* drop 'sysarticleupdates' */
  900.     IF exists (select * from sysobjects where name = 'sysarticleupdates')
  901.     BEGIN
  902.         DROP TABLE sysarticleupdates
  903.         IF @@ERROR <> 0
  904.         BEGIN
  905.             if @@trancount > 0
  906.             begin
  907.                 ROLLBACK TRAN sp_drop_central_pub_tables
  908.                 commit tran
  909.             end
  910.             RETURN(1)
  911.         END
  912.     END
  913.  
  914.     IF exists (select * from sysobjects where name = 'MSpub_identity_range')
  915.     BEGIN
  916.         DROP TABLE MSpub_identity_range
  917.         IF @@ERROR <> 0
  918.         BEGIN
  919.             if @@trancount > 0
  920.             begin
  921.                 ROLLBACK TRAN sp_drop_central_pub_tables
  922.                 commit tran
  923.             end
  924.             RETURN(1)
  925.         END
  926.     END
  927.     -- end SyncTran
  928.  
  929.     IF exists (select * from sysobjects where name = 'systranschemas' and uid = 1)
  930.     BEGIN
  931.         DROP TABLE dbo.systranschemas
  932.         IF @@ERROR <> 0
  933.         BEGIN
  934.             if @@trancount > 0
  935.             begin
  936.                 ROLLBACK TRAN sp_drop_central_pub_tables
  937.                 commit tran
  938.             end
  939.             RETURN(1)
  940.         END
  941.     END
  942.  
  943.     COMMIT TRAN
  944. GO
  945.  
  946. EXEC dbo.sp_MS_marksystemobject sp_MSdrop_pub_tables
  947. GO
  948.  
  949. dump tran master with no_log
  950. go
  951.  
  952. --print ''
  953. --print 'Executing procedure dbo.sp_MSdrop_pub_tables.'
  954. --go
  955. --exec dbo.sp_MSdrop_pub_tables
  956. --go
  957.  
  958. --dump tran master with no_log
  959. --go
  960.  
  961. /* Create and execute dbo.sp_MScreate_pub_tables */
  962.  
  963. dump tran master with no_log
  964. go
  965.  
  966. print ''
  967. print 'Creating procedure sp_MSarticlecolstatus'
  968. go
  969. CREATE PROCEDURE sp_MSarticlecolstatus (
  970.     @artid int,
  971.     @tabid int,
  972.     @colid int,
  973.     @type nvarchar (10),      /* 'publish', 'nonsqlsub' */
  974.     @status bit OUTPUT)
  975.     AS
  976.  
  977.     SELECT @status = 0
  978.  
  979.     IF LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) = N'nonsqlsub'
  980.     BEGIN
  981.  
  982.         ----------------------------------------------------------
  983.         -- Check all active or subscribed articles for the column.
  984.         ----------------------------------------------------------
  985.  
  986.         IF EXISTS( SELECT sub.artid FROM sysarticles art, syssubscriptions sub, syspublications sp, master.dbo.sysservers ss
  987.                    WHERE art.objid = @tabid
  988.                    AND art.artid <> @artid
  989.                    AND sub.artid = art.artid
  990.                    AND ss.srvid = sub.srvid
  991.                    AND sp.pubid = art.pubid
  992.                    AND ( ( sub.status in(1,2) AND (ss.srvproduct = N'MSREPL-NONSQL' OR sp.allow_anonymous = 1) ) 
  993.                          OR sub.status = 3 )
  994.                    AND CONVERT(bit, CONVERT( varbinary, SUBSTRING( CONVERT( nvarchar, art.columns ), 16 - FLOOR((@colid-1)/16),1 )) & POWER(2, ((@colid-1)%16))) = 1 )
  995.         BEGIN
  996.             SELECT @status = 1
  997.         END
  998.     END
  999.     ELSE
  1000.     BEGIN
  1001.     
  1002.         -----------------------------------------------------------
  1003.         -- Check all articles for the column.
  1004.         -----------------------------------------------------------
  1005.  
  1006.         IF EXISTS( SELECT artid FROM sysarticles 
  1007.                    WHERE objid = @tabid
  1008.                    AND artid <> @artid
  1009.                    AND CONVERT(bit, CONVERT( varbinary, SUBSTRING( CONVERT( nvarchar, columns ), 16 - FLOOR((@colid-1)/16),1 )) & POWER(2, ((@colid-1)%16))) = 1 )
  1010.         BEGIN
  1011.             SELECT @status = 1
  1012.         END
  1013.     END
  1014.  
  1015.     RETURN (0)
  1016. GO
  1017.  
  1018. EXEC dbo.sp_MS_marksystemobject sp_MSarticlecolstatus
  1019. GO
  1020.  
  1021.  
  1022. print ''
  1023. print 'Creating procedure sp_MSarticlecol'
  1024. go
  1025. CREATE PROCEDURE sp_MSarticlecol (
  1026.     @artid int,
  1027.     @colid smallint = NULL,
  1028.     @type nvarchar(10),      /* 'publish', 'nonsqlsub' */
  1029.     @operation nvarchar(5))  /* 'add', 'drop' */
  1030.     AS
  1031.  
  1032.     /*
  1033.     ** Declarations.
  1034.     */
  1035.     DECLARE @cmd nvarchar(255)
  1036.     DECLARE @cmd1 nvarchar(255)
  1037.     DECLARE @columns binary(32)    /* Temporary storage for the converted column */
  1038.     DECLARE @tabid int        /* Article base table id */
  1039.     DECLARE @retcode int
  1040.     DECLARE @status bit
  1041.     DECLARE @publish smallint        /* Constant: 0x1000 */
  1042.     DECLARE @nonsqlsub smallint        /* Constant: 0x2000 */
  1043.     DECLARE @initiated smallint            /* Constant: 0x4000 */
  1044.     DECLARE @repldts smallint            /* Constant: 0x8000 */
  1045.     DECLARE @tinycolid tinyint, @allow_dts bit, @pubid int  /* hydra compatible colid */
  1046.  
  1047.     if @colid >= 256
  1048.     begin
  1049.     raiserror(21395, 16, -1)
  1050.         RETURN (1)
  1051.     end
  1052.  
  1053.     SELECT @tinycolid = @colid
  1054.  
  1055.     SELECT @tabid = objid, @pubid = pubid FROM sysarticles WHERE artid = @artid
  1056.  
  1057.     select @allow_dts = allow_dts from syspublications where pubid = @pubid
  1058.  
  1059.  
  1060.     SELECT @publish = 0x1000
  1061.     SELECT @nonsqlsub = 0x2000
  1062.     SELECT @initiated = 0x4000
  1063.     if @allow_dts = 1
  1064.         select @repldts = 0x8000
  1065.     else
  1066.         select @repldts = 0x0000
  1067.  
  1068.     -- loop through all columns in the article
  1069.  
  1070.     IF @colid IS NULL
  1071.     BEGIN
  1072.        DECLARE hCartcol CURSOR LOCAL FAST_FORWARD FOR
  1073.             SELECT colid FROM syscolumns, sysarticles
  1074.                 WHERE artid = @artid
  1075.                 AND id = @tabid
  1076.                 AND convert(bit, convert( varbinary, substring( convert( nvarchar, columns ), 16 - floor((colid-1)/16),1 )) & power( 2, ((colid-1)%16))) = 1
  1077.     END
  1078.     ELSE
  1079.     BEGIN
  1080.        DECLARE hCartcol CURSOR LOCAL FAST_FORWARD FOR 
  1081.             SELECT colid FROM syscolumns WHERE id = @tabid
  1082.                 AND colid = @colid
  1083.     END
  1084.  
  1085.  
  1086.     OPEN hCartcol
  1087.  
  1088.     FETCH hCartcol INTO @colid
  1089.  
  1090.     WHILE (@@fetch_status <> -1)
  1091.     BEGIN
  1092.  
  1093.        IF LOWER(@operation collate SQL_Latin1_General_CP1_CS_AS) = N'add'
  1094.        BEGIN
  1095.           IF LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) = N'publish'
  1096.           BEGIN
  1097.              UPDATE syscolumns
  1098.              SET colstat = colstat | @publish
  1099.              WHERE id = @tabid
  1100.              AND colid = @colid
  1101.           END
  1102.           ELSE
  1103.           BEGIN
  1104.              UPDATE syscolumns
  1105.              SET colstat = colstat | @nonsqlsub | @repldts
  1106.              WHERE id = @tabid
  1107.              AND colid = @colid
  1108.           END
  1109.        END
  1110.        ELSE /* drop */
  1111.        BEGIN
  1112.           /*
  1113.           ** Is there another non-sql server subscription on the column?
  1114.           ** Or another article publishing the column?
  1115.           */
  1116.           EXEC @retcode = dbo.sp_MSarticlecolstatus @artid, @tabid, @colid,
  1117.           @type, @status OUTPUT
  1118.  
  1119.           IF @@error <> 0 OR @retcode <> 0
  1120.           BEGIN
  1121.              CLOSE hCartcol
  1122.             DEALLOCATE hCartcol
  1123.             RETURN (1)
  1124.           END
  1125.  
  1126.           IF (@status = 0)
  1127.           BEGIN
  1128.              IF LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) = N'publish'
  1129.              BEGIN
  1130.                 /* Clear 'publish' bit */
  1131.                 UPDATE syscolumns
  1132.                 SET colstat = colstat & ~@publish
  1133.                 WHERE id = @tabid
  1134.                 AND colid = @colid
  1135.              END
  1136.              ELSE
  1137.              BEGIN
  1138.                 /* Clear 'non-sql server subscription' bit */
  1139.                 UPDATE syscolumns
  1140.                 SET colstat = colstat & ~@nonsqlsub & ~@repldts
  1141.                 WHERE id = @tabid
  1142.                 AND colid = @colid
  1143.              END
  1144.           END
  1145.        END
  1146.  
  1147.        FETCH hCartcol INTO @colid
  1148.  
  1149.     END
  1150.  
  1151.  
  1152.     CLOSE hCartcol
  1153.     DEALLOCATE hCartcol
  1154.  
  1155. GO
  1156.  
  1157. EXEC dbo.sp_MS_marksystemobject sp_MSarticlecol
  1158. GO
  1159.  
  1160. print ''
  1161. print 'Creating procedure sp_MScreate_pub_tables'
  1162. go
  1163. CREATE PROCEDURE sp_MScreate_pub_tables
  1164. AS
  1165.     DECLARE @fError int
  1166.     SELECT @fError = 0
  1167.  
  1168.     -- enable 'create tables as pseudo system tables
  1169.  
  1170.     -- sp_MS_upd_sysobj_category is obsolete, use sp_MS_marksystemobject instead
  1171.     -- exec dbo.sp_MS_upd_sysobj_category 1
  1172.  
  1173.  
  1174.     /* 
  1175.     ** Msg 226, Level 16, State 9
  1176.     ** CREATE TABLE system-table command not allowed within multi-statement transaction.
  1177.     */
  1178.     /*
  1179.     BEGIN TRAN sp_create_central_pub_tables
  1180.     */
  1181.     
  1182.     /* Creating 'sysarticles' */
  1183.     IF not exists (select * from sysobjects where name = 'sysarticles')
  1184.     BEGIN
  1185.         create table dbo.sysarticles
  1186.         (
  1187.         artid               int                 identity NOT NULL,
  1188.         columns             varbinary(32)       NULL,
  1189.         creation_script     nvarchar(255)       NULL,
  1190.         del_cmd             nvarchar(255)       NULL,
  1191.         description         nvarchar(255)       NULL,
  1192.         dest_table          sysname             NOT NULL,
  1193.         filter              int                 NOT NULL,
  1194.         filter_clause       ntext               NULL,
  1195.         ins_cmd             nvarchar(255)       NULL,
  1196.         name                sysname             NOT NULL,
  1197.         objid               int                 NOT NULL,
  1198.         pubid               int                 NOT NULL,
  1199.         pre_creation_cmd    tinyint             NOT NULL,
  1200.         status              tinyint             NOT NULL,
  1201.         sync_objid          int                 NOT NULL,
  1202.         type                tinyint             NOT NULL,
  1203.         upd_cmd             nvarchar(255)       NULL,
  1204.         schema_option       binary(8)           NULL,
  1205.         dest_owner          sysname             NULL
  1206.         -- Note: Please update sysextendedarticlesview whenever
  1207.         -- there is a schema change in sysarticles
  1208.         )
  1209.  
  1210.         EXEC dbo.sp_MS_marksystemobject 'sysarticles'
  1211.  
  1212.         IF @@error<>0
  1213.         BEGIN
  1214.             GOTO ERROR
  1215.         END
  1216.  
  1217.         create unique nonclustered index unc1sysarticles
  1218.             on sysarticles(artid, pubid) 
  1219.         
  1220.         IF @@error<>0
  1221.         BEGIN
  1222.             GOTO ERROR
  1223.         END
  1224.  
  1225.     END
  1226.  
  1227.     /* Creating 'sysschemaarticles' */
  1228.     IF not exists (select * from sysobjects where name = 'sysschemaarticles')
  1229.     BEGIN
  1230.         create table dbo.sysschemaarticles
  1231.         (
  1232.         artid               int                 NOT NULL,
  1233.         creation_script     nvarchar(255)       NULL,
  1234.         description         nvarchar(255)       NULL,
  1235.         dest_object         sysname             NOT NULL,
  1236.         name                sysname             NOT NULL,
  1237.         objid               int                 NOT NULL,
  1238.         pubid               int                 NOT NULL,
  1239.         pre_creation_cmd    tinyint             NOT NULL,
  1240.         status              int                 NOT NULL,
  1241.         type                tinyint             NOT NULL,
  1242.         schema_option       binary(8)           NULL,
  1243.         dest_owner          sysname             NULL
  1244.         )
  1245.         
  1246.         IF @@error<>0
  1247.         BEGIN
  1248.             GOTO ERROR
  1249.         END
  1250.  
  1251.         EXEC dbo.sp_MS_marksystemobject 'sysschemaarticles'
  1252.  
  1253.         IF @@error<>0
  1254.         BEGIN
  1255.             GOTO ERROR
  1256.         END
  1257.  
  1258.         create unique nonclustered index unc1sysschemaarticles
  1259.             on sysschemaarticles(artid, pubid)
  1260.  
  1261.         IF @@error<>0
  1262.         BEGIN
  1263.             GOTO ERROR
  1264.         END
  1265.         
  1266.     END
  1267.  
  1268.     /* Creating 'sysextendedarticlesview' */
  1269.     IF not exists (select * from sysobjects where name = 'sysextendedarticlesview')
  1270.     BEGIN
  1271.         exec ('create view dbo.sysextendedarticlesview
  1272.                as
  1273.                select * from sysarticles
  1274.                union all
  1275.                select artid, NULL, creation_script, NULL, description,
  1276.                dest_object, NULL, NULL, NULL, name, objid, pubid, 
  1277.                pre_creation_cmd, status, NULL, type, NULL, 
  1278.                schema_option, dest_owner from sysschemaarticles
  1279.                go')
  1280.  
  1281.         IF @@error<>0
  1282.         BEGIN
  1283.             GOTO ERROR
  1284.         END 
  1285.  
  1286.         EXEC dbo.sp_MS_marksystemobject 'sysextendedarticlesview'
  1287.  
  1288.         IF @@error<>0
  1289.         BEGIN
  1290.             GOTO ERROR
  1291.         END
  1292.  
  1293.     END
  1294.  
  1295.     /* Creating 'syspublications' */
  1296.     IF NOT EXISTS (select * from sysobjects where name = 'syspublications')
  1297.     BEGIN
  1298.         CREATE TABLE dbo.syspublications (
  1299.         description                 nvarchar(255)   NULL,
  1300.         name                        sysname         NOT NULL,
  1301.         pubid                       int    identity NOT NULL,
  1302.         repl_freq                   tinyint         NOT NULL,
  1303.         status                      tinyint         NOT NULL,
  1304.         sync_method                 tinyint         NOT NULL,
  1305.         snapshot_jobid              binary(16)        NULL,
  1306.         independent_agent           bit             NOT NULL,
  1307.         immediate_sync              bit             NOT NULL,
  1308.         enabled_for_internet        bit             NOT NULL,
  1309.         allow_push                  bit             NOT NULL,
  1310.         allow_pull                  bit             NOT NULL,
  1311.         allow_anonymous             bit             NOT NULL,
  1312.         immediate_sync_ready        bit             NOT NULL,
  1313.         -- SyncTran
  1314.         allow_sync_tran             bit             NOT NULL,
  1315.         autogen_sync_procs          bit             NOT NULL,
  1316.         retention                   int             NULL,
  1317.         -- The following are post 7.0
  1318.         allow_queued_tran           bit   default 0    not null, 
  1319.         -- portable snapshot support
  1320.         snapshot_in_defaultfolder           bit   default 1 NOT NULL,         
  1321.         alt_snapshot_folder         nvarchar(255)   NULL,
  1322.         -- snapshot pre/post- command
  1323.         pre_snapshot_script         nvarchar(255)   NULL,
  1324.         post_snapshot_script        nvarchar(255)   NULL,
  1325.         -- Snapshot compression
  1326.         compress_snapshot           bit   default 0 NOT NULL,          
  1327.         -- Post 7.0 Ftp support
  1328.         ftp_address                 sysname         NULL,
  1329.         ftp_port                    int   default 21 NOT NULL,
  1330.         ftp_subdirectory            nvarchar(255)   NULL,
  1331.         ftp_login                   sysname         NULL default N'anonymous',
  1332.         ftp_password                nvarchar(524)   NULL,
  1333.         allow_dts        bit default 0 not null,
  1334.         allow_subscription_copy        bit default 0 not null,
  1335.         centralized_conflicts        bit                NULL, -- 0 False, 1 True
  1336.         conflict_retention            int                NULL, -- 60
  1337.         conflict_policy                int             NULL, -- 1 = PubWins, 2 = SubWins, 3 = Reinit
  1338.         queue_type                    int                NULL,  -- 1 = MSMQ, 2 = SQL
  1339.         ad_guidname                    sysname            NULL,
  1340.         backward_comp_level    int default 10 not NULL -- default is sphinx
  1341.         )
  1342.  
  1343.         EXEC dbo.sp_MS_marksystemobject 'syspublications'
  1344.  
  1345.         IF @@ERROR <> 0
  1346.         BEGIN
  1347.             GOTO ERROR
  1348.         END
  1349.  
  1350.         create unique nonclustered index unc1syspublications
  1351.             on syspublications (pubid) 
  1352.         IF @@ERROR <> 0
  1353.         BEGIN
  1354.             GOTO ERROR
  1355.         END
  1356.  
  1357.         create unique nonclustered index unc2syspublications
  1358.             on syspublications (name)
  1359.  
  1360.         IF @@ERROR <> 0
  1361.         BEGIN
  1362.             GOTO ERROR
  1363.         END
  1364.  
  1365.     END
  1366.  
  1367.        /* Creating 'syssubscriptions' */
  1368.     IF not exists (select * from sysobjects where name = 'syssubscriptions')
  1369.     BEGIN
  1370.  
  1371.         CREATE TABLE dbo.syssubscriptions
  1372.         (
  1373.         artid                    int                NOT NULL,
  1374.         srvid                    smallint        NOT NULL,
  1375.         dest_db                    sysname        NOT NULL,
  1376.         status                    tinyint            NOT NULL,
  1377.         sync_type                tinyint            NOT NULL,
  1378.         login_name                sysname        NOT NULL,
  1379.         subscription_type        int                NOT NULL,
  1380.         distribution_jobid      binary(16)          NULL,
  1381.         timestamp NOT NULL,
  1382.         -- SyncTran
  1383.         update_mode             tinyint            NOT NULL, -- 0 (read only), 1 (Sync Tran), 
  1384.                                                              -- Queued Tran
  1385.                                                              -- 2 (Queued Tran) , 3 (Failover), 4(sqlqueued), 5(sqlqueued failover)
  1386.         loopback_detection      bit NOT NULL,
  1387.           queued_reinit           bit DEFAULT 0 NOT NULL 
  1388.       )
  1389.  
  1390.         EXEC dbo.sp_MS_marksystemobject 'syssubscriptions'
  1391.  
  1392.         IF @@ERROR <> 0
  1393.         BEGIN
  1394.             GOTO ERROR
  1395.         END
  1396.  
  1397.         create unique nonclustered index unc1syssubscriptions
  1398.             on syssubscriptions (artid, srvid, dest_db)
  1399.  
  1400.         IF @@ERROR <> 0
  1401.         BEGIN
  1402.             GOTO ERROR
  1403.         END
  1404.  
  1405.     END
  1406.  
  1407.     -- SyncTran
  1408.     /* Creating 'sysarticleupdates' */
  1409.  
  1410.     IF not exists (select * from sysobjects where name = 'sysarticleupdates')
  1411.     BEGIN
  1412.  
  1413.         CREATE TABLE dbo.sysarticleupdates
  1414.         (
  1415.         artid                  int       NOT NULL,
  1416.         pubid                  int       NOT NULL,
  1417.         sync_ins_proc          int       NOT NULL,     -- ID of sproc handling Insert Sync Transactions
  1418.         sync_upd_proc          int       NOT NULL,     -- ID of sproc handling Update Sync Transactions
  1419.         sync_del_proc          int       NOT NULL,     -- ID of sproc handling Delete Sync Transactions
  1420.         autogen                bit       NOT NULL,
  1421.         sync_upd_trig          int       NOT NULL,     -- Note 7.0 upgrade issue
  1422.         conflict_tableid       int         NULL,           -- ID of conflict table for this article
  1423.         ins_conflict_proc       int         NULL,           -- ID of sproc to log conflicts
  1424.         identity_support       bit default 0 not null  -- Whether or not do auto identity range 
  1425.         )     
  1426.  
  1427.         IF @@ERROR <> 0
  1428.         BEGIN
  1429.             GOTO ERROR
  1430.         END
  1431.  
  1432.  
  1433.         -- mark the index as a system object
  1434.         exec dbo.sp_MS_marksystemobject 'sysarticleupdates'
  1435.  
  1436.         IF @@ERROR <> 0
  1437.         BEGIN
  1438.             GOTO ERROR
  1439.         END
  1440.  
  1441.         create unique nonclustered index unc1sysarticleupdates
  1442.             on sysarticleupdates (artid, pubid)
  1443.  
  1444.         IF @@ERROR <> 0
  1445.         BEGIN
  1446.             GOTO ERROR
  1447.         END
  1448.     END
  1449.     -- end SyncTran
  1450.  
  1451.  
  1452.     IF not exists (select * from sysobjects where name = 'MSpub_identity_range')
  1453.     BEGIN
  1454.         CREATE TABLE dbo.MSpub_identity_range
  1455.         (
  1456.             objid int not null,
  1457.             range bigint not null,
  1458.             pub_range bigint not null,
  1459.             current_pub_range bigint not null,
  1460.             threshold int not null,
  1461.             last_seed bigint null -- It will be not when uninitialized.
  1462.         )     
  1463.  
  1464.         IF @@ERROR <> 0
  1465.         BEGIN
  1466.             GOTO ERROR
  1467.         END
  1468.  
  1469.  
  1470.         -- mark the index as a system object
  1471.         exec dbo.sp_MS_marksystemobject 'MSpub_identity_range'
  1472.  
  1473.         IF @@ERROR <> 0
  1474.         BEGIN
  1475.             GOTO ERROR
  1476.         END
  1477.  
  1478.         create unique nonclustered index unc1MSpub_identity_range
  1479.             on MSpub_identity_range (objid)
  1480.  
  1481.         IF @@ERROR <> 0
  1482.         BEGIN
  1483.             GOTO ERROR
  1484.         END
  1485.     END
  1486.  
  1487.     IF not exists (select * from sysobjects where name = 'systranschemas' and uid = 1)
  1488.     BEGIN
  1489.         CREATE TABLE dbo.systranschemas
  1490.         (
  1491.             tabid int not null,
  1492.             startlsn binary(10) not null,
  1493.             endlsn binary(10) not null
  1494.     )     
  1495.  
  1496.         IF @@ERROR <> 0
  1497.         BEGIN
  1498.             GOTO ERROR
  1499.         END
  1500.  
  1501.         -- mark the index as a system object
  1502.         exec dbo.sp_MS_marksystemobject 'systranschemas'
  1503.  
  1504.         IF @@ERROR <> 0
  1505.         BEGIN
  1506.             GOTO ERROR
  1507.         END
  1508.  
  1509.         create unique clustered index uncsystranschemas
  1510.             on systranschemas (startlsn)
  1511.  
  1512.         IF @@ERROR <> 0
  1513.         BEGIN
  1514.             GOTO ERROR
  1515.         END
  1516.     END
  1517.  
  1518. CLEANUP:
  1519.  
  1520.     -- disable 'create tables as pseudo system tables
  1521.     -- sp_MS_upd_sysobj_category is obsolete, use sp_MS_marksystemobject instead
  1522.     -- exec dbo.sp_MS_upd_sysobj_category 2
  1523.     RETURN( @fError )
  1524.  
  1525. ERROR:
  1526.  
  1527.     select @fError = 1
  1528.     GOTO CLEANUP
  1529.  
  1530. GO
  1531.  
  1532. EXEC dbo.sp_MS_marksystemobject sp_MScreate_pub_tables
  1533. GO
  1534.  
  1535. dump tran master with no_log
  1536. go
  1537.  
  1538. /*
  1539. ** Create replication stored procedures.
  1540. ** Part 2:  create all other stored procedures.
  1541. */
  1542.  
  1543. create proc sp_MSsetfilterparent @filter_name nvarchar(386), @parent_id int
  1544. as
  1545.    -- SQL SERVER 7.0 ONLY update sysobjects, set parent id = underlying
  1546.    -- object id
  1547.  
  1548.     declare @retcode int
  1549.     exec @retcode = dbo.sp_MSreplcheck_publish
  1550.     if @@ERROR <> 0 or @retcode <> 0
  1551.         return(1)
  1552.  
  1553.     -- Don't bother to do anything if filter name is null or empty
  1554.     if @filter_name is null or @filter_name = N''
  1555.         return 0
  1556.  
  1557.  
  1558.    BEGIN TRAN
  1559.  
  1560.    exec dbo.sp_replupdateschema @filter_name 
  1561.    update sysobjects set parent_obj = @parent_id where id = object_id( @filter_name )
  1562.    exec dbo.sp_replupdateschema @filter_name 
  1563.  
  1564.    COMMIT TRAN
  1565.  
  1566. go
  1567.  
  1568.  
  1569. EXEC dbo.sp_MS_marksystemobject sp_MSsetfilterparent
  1570. GO
  1571.  
  1572. create proc sp_MSdoesfilterhaveparent @filter_id int
  1573. as
  1574.     declare @retcode int
  1575.     exec @retcode = dbo.sp_MSreplcheck_publish
  1576.     if @@ERROR <> 0 or @retcode <> 0
  1577.         return(1)
  1578.  
  1579.     if exists ( select * from sysobjects
  1580.                 where id = @filter_id and
  1581.                 parent_obj <> 0 )
  1582.     BEGIN
  1583.         return 1
  1584.     END
  1585.     ELSE
  1586.     BEGIN
  1587.         return 0
  1588.     END
  1589. go
  1590.  
  1591. EXEC dbo.sp_MS_marksystemobject sp_MSdoesfilterhaveparent
  1592. GO
  1593.  
  1594.  
  1595. create proc sp_MSsetfilteredstatus @object_id int
  1596. as
  1597.     declare @qualified_name nvarchar(512)
  1598.  
  1599.     declare @retcode int
  1600.     exec @retcode = dbo.sp_MSreplcheck_publish
  1601.     if @@ERROR <> 0 or @retcode <> 0
  1602.         return(1)
  1603.  
  1604.     exec dbo.sp_MSget_qualified_name @object_id, @qualified_name output
  1605.  
  1606.    BEGIN TRANSACTION
  1607.    
  1608.    exec dbo.sp_replupdateschema @qualified_name
  1609.         
  1610.    if exists( select * from sysobjects where type = 'RF' and parent_obj = @object_id )
  1611.       or exists( select * from sysarticles where objid = @object_id and ( upd_cmd like 'CALL%' OR upd_cmd like 'XCALL%' ) 
  1612.       or exists( select * from sysarticles sa, syssubscriptions ss where sa.artid = ss.artid and ss.status = 3) )
  1613.    begin
  1614.        update sysobjects set replinfo = replinfo | 32 where id = @object_id
  1615.    end
  1616.    else
  1617.    begin
  1618.        update sysobjects set replinfo = replinfo & ~32 where id = @object_id
  1619.    end
  1620.  
  1621.    exec dbo.sp_replupdateschema @qualified_name
  1622.  
  1623.    COMMIT TRANSACTION
  1624.    
  1625. go
  1626.  
  1627. EXEC dbo.sp_MS_marksystemobject sp_MSsetfilteredstatus
  1628. GO
  1629.  
  1630. CREATE PROCEDURE sp_MSretrieve_publication 
  1631. @publication sysname
  1632. AS
  1633. declare @retcode int
  1634. /*
  1635. ** Security Check
  1636. */
  1637. exec @retcode = dbo.sp_MSreplcheck_publish
  1638. if @@ERROR <> 0 or @retcode <> 0
  1639.     return(1)
  1640.  
  1641. select 'Name' = name, 
  1642.         'database ' = db_name(), 
  1643.         'publisher' = @@SERVERNAME, 
  1644.         'type' = case when LOWER(repl_freq)=1 then 'Snapshot' else 'Transactional' end, 
  1645.         'description ' = description, 
  1646.         'status ' = status,  
  1647.         'allow known pull subscription' = allow_pull, 
  1648.         'allow immediate-updating subscription ' = allow_sync_tran,
  1649.         'allow anonymous ' = allow_anonymous,  
  1650.         'allow queued-updating subscription ' = allow_queued_tran, 
  1651.         'allow snapshot files FTP downloading' = enabled_for_internet, 
  1652.         'third party' = sync_method 
  1653.     from syspublications
  1654.     where name = @publication
  1655. go
  1656.  
  1657. EXEC dbo.sp_MS_marksystemobject sp_MSretrieve_publication
  1658. GO
  1659.  
  1660.  
  1661.  
  1662. CREATE PROCEDURE sp_MSreplsup_table_has_pk @tabid INT
  1663. as
  1664.  
  1665. -- if it's a table, check that it has a PK
  1666. -- if it's a view, see if it has an index ( MVs must have a unique CI )
  1667.  
  1668.     IF EXISTS (SELECT so1.* FROM sysobjects so1, sysobjects so2
  1669.                    WHERE so1.parent_obj = @tabid
  1670.                    AND so1.xtype = 'PK'
  1671.                    AND so2.id = so1.parent_obj
  1672.                    AND so2.xtype = 'U')
  1673.     BEGIN
  1674.         RETURN 1
  1675.     END
  1676.  
  1677.     IF EXISTS (SELECT * from sysobjects so, sysindexes si
  1678.                     WHERE so.id = @tabid
  1679.                     AND so.xtype = 'V'
  1680.                     AND si.id = so.id )
  1681.     BEGIN
  1682.         -- evaluate keys, make sure none are nullable
  1683.         DECLARE @indkey int
  1684.         DECLARE @objname nvarchar(256)
  1685.  
  1686.         SELECT @indkey = 1
  1687.         select @objname = QUOTENAME(user_name(OBJECTPROPERTY(@tabid, 'OwnerId'))) collate database_default + N'.' + QUOTENAME(object_name( @tabid )) collate database_default 
  1688.  
  1689.         WHILE @indkey <= 16 and index_col( @objname, 1, @indkey ) is not null
  1690.         BEGIN
  1691.             IF NOT EXISTS( SELECT * FROM syscolumns 
  1692.                         WHERE id = @tabid
  1693.                         AND name = index_col( @objname, 1, @indkey )
  1694.                         AND isnullable = 0 )
  1695.             BEGIN
  1696.                 RETURN 0
  1697.             END
  1698.  
  1699.             SELECT @indkey = @indkey + 1
  1700.         END
  1701.         RETURN 1
  1702.     END
  1703.     ELSE
  1704.     BEGIN
  1705.         RETURN 0
  1706.     END
  1707. go
  1708.  
  1709. EXEC dbo.sp_MS_marksystemobject sp_MSreplsup_table_has_pk
  1710. GO
  1711.  
  1712. CREATE PROCEDURE sp_replsync (
  1713.     @publisher sysname,    
  1714.     @publisher_db sysname,        
  1715.     @publication sysname,    
  1716.     @article sysname = '%' 
  1717.     ) AS
  1718.  
  1719.     SET NOCOUNT ON
  1720.     RAISERROR (21023, 16, -1,'sp_replsync')
  1721.     RETURN(1)
  1722. GO
  1723.  
  1724. EXEC dbo.sp_MS_marksystemobject sp_replsync
  1725. GO
  1726.  
  1727.  
  1728. print ''
  1729. print 'Creating procedure sp_enumfullsubscriber'
  1730. go
  1731.  
  1732. CREATE PROCEDURE sp_enumfullsubscribers (
  1733.         @publication sysname = '%'      /* The publication name */
  1734.     ) AS
  1735.  
  1736.     /*
  1737.     ** Declarations.
  1738.     */
  1739.  
  1740.     DECLARE @retcode int
  1741.  
  1742.     /*
  1743.     ** Security Check
  1744.     */
  1745.     exec @retcode = dbo.sp_MSreplcheck_publish
  1746.     if @@ERROR <> 0 or @retcode <> 0
  1747.         return(1)
  1748.  
  1749.     /*
  1750.     ** Parameter Check: @publication.
  1751.     ** Check to make sure that the publication exists and that it conforms
  1752.     ** to the rules for identifiers.
  1753.     */
  1754.  
  1755.     IF @publication IS NOT NULL
  1756.         BEGIN
  1757.  
  1758.             IF @publication <> '%'
  1759.                 BEGIN
  1760.                     EXECUTE @retcode = dbo.sp_validname @publication
  1761.  
  1762.                     IF @retcode <> 0
  1763.                     RETURN (1)
  1764.                 END
  1765.  
  1766.             IF NOT EXISTS (SELECT * FROM syspublications WHERE name LIKE @publication)
  1767.                 BEGIN
  1768.                     RAISERROR (20026, 11, -1, @publication)
  1769.                     RETURN (1)
  1770.                 END
  1771.  
  1772.         END
  1773.  
  1774.     ELSE
  1775.         BEGIN
  1776.             RAISERROR (14043, 16, -1, '@publication')
  1777.             RETURN (1)
  1778.         END
  1779.  
  1780.     /*
  1781.     ** Select all subscribers who subscribe to all articles in the desired
  1782.     ** publication.
  1783.     */
  1784.  
  1785.     SELECT DISTINCT 'subscriber' = sv.srvname
  1786.       FROM syspublications p,
  1787.            sysextendedarticlesview s,
  1788.            syssubscriptions ss,
  1789.            master..sysservers sv
  1790.      WHERE p.name LIKE @publication collate database_default
  1791.        AND p.pubid = s.pubid
  1792.        AND s.artid = ss.artid
  1793.        AND ss.srvid = sv.srvid
  1794.        AND NOT EXISTS (SELECT *
  1795.                          FROM sysextendedarticlesview s2
  1796.                         WHERE s2.pubid = p.pubid
  1797.                           AND NOT EXISTS (SELECT *
  1798.                                             FROM syssubscriptions ss2,
  1799.                                                  master..sysservers sv2
  1800.                                            WHERE s2.artid = ss2.artid
  1801.                                              AND ss2.srvid = sv2.srvid
  1802.                                              AND sv2.srvid = sv.srvid))
  1803. go
  1804.  
  1805.  
  1806. EXEC dbo.sp_MS_marksystemobject sp_enumfullsubscribers
  1807. GO
  1808.  
  1809. print ''
  1810. print 'Creating procedure sp_addpublication.'
  1811. go
  1812.  
  1813.  
  1814. CREATE PROCEDURE sp_addpublication (
  1815.     @publication            sysname,                          /* publication name */
  1816.     @taskid                    int = 0,                          /* backward compatible */
  1817.     @restricted                nvarchar (10) = 'false',          /* publication security */
  1818.     @sync_method            nvarchar(13) = 'native',          /* (bcp) native, (bcp) character */
  1819.     @repl_freq                nvarchar(10) = 'continuous',      /* continuous, snapshot */
  1820.     @description            nvarchar (255) = NULL,            /* publication description */
  1821.     @status                    nvarchar(8) = 'inactive',         /* publication status; 0=inactive, 1=active */
  1822.     @independent_agent        nvarchar(5) = 'false',            /* true or false */
  1823.     @immediate_sync            nvarchar(5) = 'false',            /* true or false */
  1824.     @enabled_for_internet    nvarchar(5) = 'false',            /* true or false */
  1825.     @allow_push                nvarchar(5) = 'true',             /* true or false */
  1826.     @allow_pull                nvarchar(5) = 'false',            /* true or false */
  1827.     @allow_anonymous        nvarchar(5) = 'false',            /* true or false */
  1828.     -- SyncTran
  1829.     @allow_sync_tran        nvarchar(5) = 'false',            /* true or false */
  1830.     @autogen_sync_procs        nvarchar(5) = 'true',             /* auto gen sync tran procs per article */
  1831.     @retention                int = 336,                        /* 14  days */
  1832.     @allow_queued_tran      nvarchar(5) = 'false',
  1833.     -- Portable Snapshot
  1834.     @snapshot_in_defaultfolder      nvarchar(5) = 'true',
  1835.     @alt_snapshot_folder    nvarchar(255) = NULL,
  1836.     -- Snapshot pre/post- commands
  1837.     @pre_snapshot_script    nvarchar(255) = NULL,
  1838.     @post_snapshot_script   nvarchar(255) = NULL,
  1839.     -- Snapshot compression
  1840.     @compress_snapshot      nvarchar(5) = 'false',
  1841.     -- Post 7.0 FTP
  1842.     @ftp_address            sysname = NULL,
  1843.     @ftp_port                   int = 21,
  1844.     @ftp_subdirectory       nvarchar(255) = NULL,
  1845.     @ftp_login              sysname = N'anonymous',
  1846.     @ftp_password           sysname = NULL,
  1847.     @allow_dts                nvarchar(5)    = 'false',
  1848.     @allow_subscription_copy nvarchar(5) = 'false',
  1849.     @conflict_policy        nvarchar(100) = NULL,     -- NULL, 'pub wins', 'sub reinit', 'sub wins'
  1850.     @centralized_conflicts    nvarchar(5) = NULL,     -- NULL, 'true', 'false'
  1851.     @conflict_retention        int = 14,
  1852.     @queue_type                nvarchar(10) = NULL,    -- NULL, 'msmq', 'sql'
  1853.     @add_to_active_directory    nvarchar(10) = 'false',
  1854.     @logreader_job_name sysname = NULL,
  1855.     @qreader_job_name sysname = NULL
  1856.     ) 
  1857. AS
  1858. BEGIN
  1859.  
  1860.     SET NOCOUNT ON
  1861.  
  1862.     /*
  1863.     ** Declarations.
  1864.     */
  1865.  
  1866.     DECLARE @retcode    int         /* return code value for procedure execution */
  1867.     DECLARE @rfid tinyint           /* identifier for replication frequency */
  1868.     DECLARE @publish_bit smallint   /* publication bit (flag) in sysobjects */
  1869.     DECLARE @smid tinyint           /* identifier for sync method */
  1870.     DECLARE @statid tinyint         /* status id based on @status */
  1871.     DECLARE @subs_type_id tinyint   /* subscription type id based on @subscription_type */
  1872.     DECLARE @distributor sysname
  1873.     DECLARE @distribdb sysname
  1874.     DECLARE @distproc nvarchar (255)
  1875.     DECLARE @agentname nvarchar (40)
  1876.     DECLARE @dbname sysname
  1877.     DECLARE @mergepublish_bit smallint
  1878.     DECLARE @found int
  1879.     DECLARE @independent_agent_id bit
  1880.     DECLARE @immediate_sync_id bit
  1881.     DECLARE @enabled_for_internet_id bit
  1882.     DECLARE @allow_push_id bit
  1883.     DECLARE @allow_pull_id bit
  1884.     DECLARE @allow_anonymous_id bit
  1885.     DECLARE @pubid int
  1886.     declare @distgroup sysname
  1887.     DECLARE @enc_ftp_password nvarchar(524)
  1888.     DECLARE @ad_guidname    sysname
  1889.     
  1890.     -- SyncTran
  1891.     DECLARE @allow_sync_tran_id bit
  1892.     DECLARE @allow_queued_tran_id bit
  1893.     DECLARE @autogen_sync_procs_id bit
  1894.     DECLARE @conflict_policy_id int
  1895.     DECLARE @centralized_conflicts_bit bit
  1896.             , @queue_type_val int
  1897.     
  1898.     -- Portable snapshot
  1899.     DECLARE @snapshot_in_defaultfolder_bit int 
  1900.  
  1901.     -- Snapshot compression
  1902.     DECLARE @compress_snapshot_bit bit
  1903.  
  1904.     declare @qv_replication varchar(10)
  1905.     declare @qv_replication_unlimited integer
  1906.     declare @qv_value_replication integer
  1907.  
  1908.     declare @backward_comp_level int
  1909.     select @backward_comp_level = 10 -- default to sphinx
  1910.     select @allow_sync_tran_id = 0
  1911.             ,@autogen_sync_procs_id = 0
  1912.             ,@allow_queued_tran_id = 0
  1913.             ,@qv_replication = '2745196162'
  1914.             ,@qv_replication_unlimited = 0
  1915.     
  1916.     /*
  1917.     ** The default value for TRAN publication is always 72 hours
  1918.     */
  1919.     if @retention is NULL
  1920.     BEGIN
  1921.         RAISERROR(20081, 16, -1, 'retention')
  1922.         RETURN (1)
  1923.     END
  1924.     
  1925.     /*
  1926.     **  A @retention value of zero means an infinite retention period
  1927.     */
  1928.     if @retention < 0
  1929.     BEGIN
  1930.         RAISERROR (20050, 16, -1, 1)
  1931.         RETURN(1)
  1932.     END
  1933.  
  1934.     SELECT @publish_bit         = 32
  1935.     SELECT @mergepublish_bit    = 4
  1936.  
  1937.     /*
  1938.     ** Security Check
  1939.     */
  1940.  
  1941.     exec @retcode = dbo.sp_MSreplcheck_publish
  1942.     if @@ERROR <> 0 or @retcode <> 0
  1943.         return(1)
  1944.  
  1945.     /*
  1946.     ** Check to see if the database has been activated for publication.
  1947.     */
  1948.  
  1949.     IF (SELECT category & 1
  1950.           FROM master..sysdatabases
  1951.          WHERE name = DB_NAME() collate database_default) = 0
  1952.  
  1953.     BEGIN
  1954.         RAISERROR (14013, 16, -1)
  1955.         RETURN (1)
  1956.     END
  1957.  
  1958.     IF @taskid <> 0
  1959.     BEGIN
  1960.         -- No longer supported
  1961.         RAISERROR (21023, 16, -1,'@taskid')
  1962.         RETURN(1)
  1963.     END
  1964.  
  1965.     /*
  1966.     ** Parameter Check: @publication.
  1967.     ** The @publication name must conform to the rules for identifiers,
  1968.     ** and must not be the keyword 'all'.
  1969.     */
  1970.  
  1971.     IF @publication IS NULL
  1972.         BEGIN
  1973.             RAISERROR (14043, 16, -1, '@publication')
  1974.             RETURN (1)
  1975.         END
  1976.  
  1977.     exec @retcode = dbo.sp_MSreplcheck_name @publication
  1978.     if @@ERROR <> 0 or @retcode <> 0
  1979.         return(1)
  1980.  
  1981.     IF LOWER (@publication) = 'all'
  1982.         BEGIN
  1983.             RAISERROR (14034, 16, -1)
  1984.             RETURN (1)
  1985.         END
  1986.  
  1987.     /*
  1988.     **  Check if the publication already exists.
  1989.     **  1. Check transaction-level publications
  1990.     **  2. Check merge publications
  1991.     */
  1992.  
  1993.     IF EXISTS (SELECT * FROM syspublications WHERE name = @publication)
  1994.         BEGIN
  1995.             RAISERROR (14016, 16, -1, @publication)
  1996.             RETURN (1)
  1997.         END
  1998.     
  1999.     if (select category & @mergepublish_bit from master..sysdatabases where name = DB_NAME() collate database_default) <> 0
  2000.         begin
  2001.             EXEC @retcode = dbo.sp_helpmergepublication @publication, @found output
  2002.  
  2003.             IF @@ERROR <> 0 OR @retcode <> 0
  2004.             BEGIN
  2005.                 RETURN (1)
  2006.             END
  2007.  
  2008.             IF @found <> 0 
  2009.             BEGIN
  2010.                 RAISERROR (20025, 16, -1, @publication)
  2011.                 RETURN (1)
  2012.             END
  2013.         end
  2014.  
  2015.     /*
  2016.     ** Get distribution server information for remote RPC
  2017.     ** agent verification.
  2018.     */
  2019.     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  2020.                  @distribdb = @distribdb OUTPUT
  2021.  
  2022.     IF @@error <> 0 OR @retcode <> 0
  2023.         BEGIN
  2024.         RAISERROR (14071, 16, -1)
  2025.             RETURN (1)
  2026.     END
  2027.  
  2028.  
  2029.     /*
  2030.     ** Parameter Check: @sync_method
  2031.     ** The synchronization method must be one of the following:
  2032.     **
  2033.     **      0  [bcp] native
  2034.     **      1  [bcp] character
  2035.     **        2  dump database
  2036.     **        3  concurrent
  2037.     **        4  concurrent character
  2038.     */
  2039.  
  2040.     SELECT @sync_method = LOWER(@sync_method collate SQL_Latin1_General_CP1_CS_AS)                                        
  2041.  
  2042.     IF @sync_method IS NULL OR @sync_method NOT IN ('native', 'character', 'bcp native', 'bcp character', 'dump database', 'concurrent', 'concurrent_c')
  2043.         BEGIN
  2044.             RAISERROR (14014, 16, -1)
  2045.             RETURN (1)
  2046.         END
  2047.  
  2048.     IF @sync_method = 'concurrent_c'
  2049.         SELECT @smid = 4
  2050.     ELSE IF @sync_method = 'concurrent'
  2051.         SELECT @smid = 3
  2052.     ELSE IF @sync_method = 'dump database'
  2053.     begin
  2054.         SELECT @smid = 2                   
  2055.         select @backward_comp_level = 40 -- not sure if we are using this, but has to be shiloh feature
  2056.     end
  2057.     ELSE IF @sync_method IN ('character', 'bcp character')
  2058.         SELECT @smid = 1
  2059.     ELSE 
  2060.         SELECT @smid = 0
  2061.  
  2062.     /*
  2063.     ** Parameter Check: @repl_freq.
  2064.     ** Make sure that the replication frequency is one of the following:
  2065.     **
  2066.     **  id  frequency
  2067.     **  ==  ==========
  2068.     **   0  continuous
  2069.     **   1  snapshot
  2070.     */
  2071.  
  2072.     SELECT @repl_freq = LOWER(@repl_freq collate SQL_Latin1_General_CP1_CS_AS)
  2073.     IF @repl_freq IS NULL OR @repl_freq NOT IN ('continuous', 'snapshot')
  2074.         BEGIN
  2075.             RAISERROR (14015, 16, -1)
  2076.             RETURN (1)
  2077.         END
  2078.  
  2079.     IF @repl_freq = 'snapshot' SELECT @rfid = 1
  2080.     ELSE SELECT @rfid = 0
  2081.  
  2082.     -- disable tran publishing on REPLICATION_LIMITED sku
  2083.     exec @qv_value_replication = master.dbo.sp_MSinstance_qv @qv_replication     
  2084.     if (@rfid = 0) and ( @qv_value_replication != @qv_replication_unlimited ) 
  2085.     begin
  2086.         raiserror(21108, 16, -1)
  2087.         return (1)
  2088.     end
  2089.  
  2090.     /*
  2091.     ** Parameter Check:  @restricted.
  2092.     */
  2093.  
  2094.     IF (@restricted IS NULL) OR (LOWER(@restricted collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false'))
  2095.         BEGIN
  2096.             RAISERROR (14017, 16, -1)
  2097.             RETURN (1)
  2098.         END
  2099.  
  2100.     /*
  2101.     ** Restricted publications are no longer supported
  2102.     */
  2103.     IF LOWER(@restricted collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  2104.     BEGIN
  2105.         RAISERROR (14147, 16, -1)
  2106.         RETURN(1)
  2107.     END
  2108.  
  2109.     /*
  2110.     ** Parameter Check:  @status.
  2111.     ** The @status value can be:
  2112.     **
  2113.     **      statid  status
  2114.     **      ======  ========
  2115.     **           0  inactive
  2116.     **           1  active
  2117.     */
  2118.  
  2119.     IF @status IS NULL OR LOWER(@status collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('inactive', 'active')
  2120.         BEGIN
  2121.             RAISERROR (14012, 16, -1)
  2122.             RETURN (1)
  2123.         END
  2124.  
  2125.     IF LOWER(@status collate SQL_Latin1_General_CP1_CS_AS) = 'active' 
  2126.     begin
  2127.         SELECT @statid = 1
  2128.     end
  2129.     ELSE 
  2130.     begin
  2131.         SELECT @statid = 0
  2132.     end
  2133.  
  2134.     /*
  2135.     ** Parameter Check:  @independent_agent.
  2136.     */
  2137.  
  2138.     IF @independent_agent IS NULL OR LOWER(@independent_agent collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  2139.         BEGIN
  2140.             RAISERROR (14148, 16, -1, '@independent_agent')
  2141.             RETURN (1)
  2142.         END
  2143.  
  2144.     IF LOWER(@independent_agent collate SQL_Latin1_General_CP1_CS_AS) = 'true' SELECT @independent_agent_id = 1
  2145.     ELSE SELECT @independent_agent_id = 0
  2146.  
  2147.     /*
  2148.     ** Parameter Check:  @immediate_sync.
  2149.     */
  2150.  
  2151.     IF @immediate_sync IS NULL OR LOWER(@immediate_sync collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  2152.         BEGIN
  2153.             RAISERROR (14148, 16, -1, '@immediate_sync')
  2154.             RETURN (1)
  2155.         END
  2156.  
  2157.     IF LOWER(@immediate_sync collate SQL_Latin1_General_CP1_CS_AS) = 'true' SELECT @immediate_sync_id = 1
  2158.     ELSE SELECT @immediate_sync_id = 0
  2159.  
  2160.     /*
  2161.     ** Parameter Check:  @enabled_for_internet.
  2162.     */
  2163.  
  2164.     IF @enabled_for_internet IS NULL OR LOWER(@enabled_for_internet collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  2165.         BEGIN
  2166.             RAISERROR (14148, 16, -1, '@enabled_for_internet')
  2167.             RETURN (1)
  2168.         END
  2169.  
  2170.     IF LOWER(@enabled_for_internet collate SQL_Latin1_General_CP1_CS_AS) = 'true' SELECT @enabled_for_internet_id = 1
  2171.     ELSE SELECT @enabled_for_internet_id = 0
  2172.  
  2173.     IF @enabled_for_internet_id = 1 AND (@alt_snapshot_folder IS NULL OR
  2174.         @alt_snapshot_folder = N'')
  2175.         BEGIN
  2176.             RAISERROR (21159, 16, -1)
  2177.             RETURN (1) 
  2178.         END
  2179.  
  2180.     /*
  2181.     ** Parameter Check:  @allow_push.
  2182.     */
  2183.  
  2184.     IF @allow_push IS NULL OR LOWER(@allow_push collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  2185.         BEGIN
  2186.             RAISERROR (14148, 16, -1, '@allow_push')
  2187.             RETURN (1)
  2188.         END
  2189.     IF LOWER(@allow_push collate SQL_Latin1_General_CP1_CS_AS) = 'true' SELECT @allow_push_id = 1
  2190.     ELSE SELECT @allow_push_id = 0
  2191.  
  2192.     /*
  2193.     ** Parameter Check:  @allow_pull.
  2194.     */
  2195.  
  2196.     IF @allow_pull IS NULL OR LOWER(@allow_pull collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  2197.         BEGIN
  2198.             RAISERROR (14148, 16, -1, '@allow_pull')
  2199.             RETURN (1)
  2200.         END
  2201.     IF LOWER(@allow_pull collate SQL_Latin1_General_CP1_CS_AS) = 'true' SELECT @allow_pull_id = 1
  2202.     ELSE SELECT @allow_pull_id = 0
  2203.  
  2204.     /*
  2205.     ** Parameter Check:  @allow_anonymous.
  2206.     */
  2207.  
  2208.     IF @allow_anonymous IS NULL OR LOWER(@allow_anonymous collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  2209.         BEGIN
  2210.             RAISERROR (14148, 16, -1, '@allow_anonymous')
  2211.             RETURN (1)
  2212.         END
  2213.     IF LOWER(@allow_anonymous collate SQL_Latin1_General_CP1_CS_AS) = 'true' SELECT @allow_anonymous_id = 1
  2214.     ELSE SELECT @allow_anonymous_id = 0
  2215.  
  2216.     /* Immediate_sync publications have to be independent_agent */
  2217.     IF @immediate_sync_id = 1 AND @independent_agent_id = 0
  2218.     BEGIN
  2219.             RAISERROR (21022, 16, -1)
  2220.             RETURN (1)
  2221.     END
  2222.  
  2223.     /*
  2224.     ** Parameter Check:  @add_to_active_directory.
  2225.     */
  2226.  
  2227.     if LOWER(@add_to_active_directory collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  2228.         BEGIN
  2229.             RAISERROR (14148, 16, -1, '@add_to_active_directory')
  2230.             RETURN (1)
  2231.         END
  2232.  
  2233.    /* Is AD supported? */
  2234.    DECLARE @retval  INT
  2235.    EXECUTE @retval = master.dbo.xp_MSADEnabled
  2236.    if (@retval <> 0) and LOWER(@add_to_active_directory collate SQL_Latin1_General_CP1_CS_AS)='true'
  2237.    begin
  2238.         RAISERROR(21253, 16, -1)
  2239.         RETURN (1)
  2240.    end
  2241.  
  2242.     /* 
  2243.     ** Non-immediate sync do not support anonymous subscriptions.
  2244.     */
  2245.     IF @immediate_sync_id = 0 AND @allow_anonymous_id = 1
  2246.     BEGIN
  2247.             RAISERROR (20011, 16, -1)
  2248.             RETURN (1)
  2249.     END
  2250.  
  2251.     -- SyncTran
  2252.     /*
  2253.     ** Parameter Check:  @allow_sync_tran
  2254.     */
  2255.  
  2256.     IF @allow_sync_tran IS NULL OR LOWER(@allow_sync_tran collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  2257.     BEGIN
  2258.         RAISERROR (14148, 16, -1, '@allow_sync_tran')
  2259.         RETURN (1)
  2260.     END
  2261.  
  2262.     /*
  2263.     ** Parameter Check:  @allow_queued_tran
  2264.     */
  2265.  
  2266.     IF @allow_queued_tran IS NULL OR LOWER(@allow_queued_tran collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  2267.     BEGIN
  2268.         RAISERROR (14148, 16, -1, '@allow_queued_tran')
  2269.         RETURN (1)
  2270.     END
  2271.  
  2272.     IF LOWER(@allow_sync_tran collate SQL_Latin1_General_CP1_CS_AS) = 'true' 
  2273.     BEGIN
  2274.         -- If we are doing sync tran, we need independent agents
  2275.         -- override the user input
  2276.         SELECT @allow_sync_tran_id = 1
  2277.             ,@independent_agent = 'true'
  2278.             ,@independent_agent_id = 1
  2279.             ,@backward_comp_level = 40 -- immediate update needs to have the new sp_addsynctriggers stored proc
  2280.     END
  2281.     ELSE 
  2282.     BEGIN
  2283.         SELECT @allow_sync_tran_id = 0
  2284.     END
  2285.  
  2286.     IF LOWER(@allow_queued_tran collate SQL_Latin1_General_CP1_CS_AS) = 'true' 
  2287.     BEGIN
  2288.         -- If we are doing queued tran, we need independent agents
  2289.         -- override the user input
  2290.         SELECT @allow_queued_tran_id = 1
  2291.             ,@independent_agent = 'true'
  2292.             ,@independent_agent_id = 1
  2293.             ,@backward_comp_level = 40 -- queued compenents not avaliable prior to shiloh
  2294.     END
  2295.     ELSE 
  2296.     BEGIN
  2297.         SELECT @allow_queued_tran_id = 0
  2298.     END
  2299.  
  2300.     --Parameter Check:  @autogen_sync_procs
  2301.     IF @autogen_sync_procs IS NULL OR LOWER(@autogen_sync_procs collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  2302.     BEGIN                                 
  2303.         RAISERROR (14148, 16, -1, '@autogen_sync_procs')
  2304.         RETURN (1)
  2305.     END
  2306.  
  2307.     --
  2308.     -- For publications that allow updating subscribers (immediate/queued)
  2309.     -- this option has to be true at all times, for others
  2310.     -- it should be false. This flag is not of any value currently
  2311.     -- as we do not have any provision for accepting custom generated
  2312.     -- synctan proc names for an article. For now, we will override
  2313.     -- the user supplied value
  2314.     --
  2315.     select @autogen_sync_procs_id = case 
  2316.         when (@allow_sync_tran_id = 0 and @allow_queued_tran_id = 0) then 0
  2317.         else 1
  2318.     end
  2319.     
  2320.     -- Portable snapshot
  2321.     IF @snapshot_in_defaultfolder IS NULL OR LOWER(@snapshot_in_defaultfolder collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  2322.     BEGIN
  2323.         RAISERROR (14148, 16, -1, '@snapshot_in_defaultfolder')
  2324.         RETURN (1)
  2325.     END
  2326.     
  2327.     IF LOWER(@snapshot_in_defaultfolder collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  2328.     BEGIN
  2329.         SELECT @snapshot_in_defaultfolder_bit = 1
  2330.     END
  2331.     ELSE
  2332.     BEGIN
  2333.         SELECT @snapshot_in_defaultfolder_bit = 0
  2334.     END
  2335.  
  2336.     -- Pre/Post snapshot commands
  2337.     -- If @sync_method is character mode bcp, this would indicate that
  2338.     -- this publication may support non-SQL Server subscribers. In this 
  2339.     -- case, pre- and post- snapshot commands are not allowed.
  2340.     IF @smid = 1 AND 
  2341.         ((@pre_snapshot_script IS NOT NULL AND @pre_snapshot_script <> '') OR
  2342.          (@post_snapshot_script IS NOT NULL AND @post_snapshot_script <> ''))
  2343.     BEGIN
  2344.         RAISERROR (21151, 16, -1)
  2345.         RETURN (1)
  2346.     END
  2347.     
  2348.     -- Parameter check - @compress_snapshot
  2349.     -- @compress_snapshot can be 1 if @alt_snapshot_folder is non-null
  2350.     IF LOWER(@compress_snapshot collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  2351.     BEGIN
  2352.         RAISERROR (14148, 16, -1, '@compress_snapshot')
  2353.         RETURN (1)
  2354.     END
  2355.     
  2356.     IF LOWER(@compress_snapshot collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  2357.     BEGIN
  2358.         SELECT @compress_snapshot_bit = 1
  2359.     END
  2360.     ELSE
  2361.     BEGIN
  2362.         SELECT @compress_snapshot_bit = 0
  2363.     END
  2364.  
  2365.     -- Snapshot compression can only be enabled if an alternate 
  2366.     -- snapshot generation folder exists or the publication
  2367.     -- is enabled for internet.
  2368.     IF (@compress_snapshot_bit = 1 AND 
  2369.         (@alt_snapshot_folder IS NULL OR @alt_snapshot_folder = N'') AND
  2370.         (LOWER(@enabled_for_internet collate SQL_Latin1_General_CP1_CS_AS) = N'false'))
  2371.     BEGIN
  2372.         RAISERROR (21157, 16, -1)
  2373.         RETURN (1)
  2374.     END    
  2375.  
  2376.     -- Parameter check: ftp_address
  2377.     -- If the publication is enabled for internet, ftp_address cannot be null
  2378.     IF @enabled_for_internet_id = 1 AND (@ftp_address IS NULL OR @ftp_address = N'')
  2379.     BEGIN
  2380.         RAISERROR (21158, 16, -1)
  2381.         RETURN (1)
  2382.     END     
  2383.  
  2384.     -- Parameter check: ftp_port
  2385.     IF @ftp_port IS NULL
  2386.     BEGIN
  2387.         RAISERROR (21160, 16, -1)
  2388.     END
  2389.  
  2390.     -- Parameter check : DTS
  2391.     declare @allow_dts_id bit
  2392.     IF @allow_dts IS NULL OR LOWER(@allow_dts collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  2393.     BEGIN
  2394.         RAISERROR (14148, 16, -1, '@allow_dts')
  2395.         RETURN (1)
  2396.     END
  2397.  
  2398.     -- Encrypt ftp password before putting it into the syspublications
  2399.     -- table if one is provided
  2400.     SELECT @enc_ftp_password = NULL
  2401.     IF @ftp_password IS NOT NULL
  2402.     BEGIN
  2403.         SELECT @enc_ftp_password = @ftp_password 
  2404.         EXEC @retcode = master.dbo.xp_repl_encrypt @enc_ftp_password OUTPUT
  2405.         IF @retcode <> 0
  2406.         BEGIN
  2407.             RETURN (1)
  2408.         END
  2409.     END    
  2410.  
  2411.     IF LOWER(@allow_dts collate SQL_Latin1_General_CP1_CS_AS) = 'true' SELECT @allow_dts_id = 1
  2412.     ELSE SELECT @allow_dts_id = 0
  2413.  
  2414.     -- To allow DTS, the publication has to be
  2415.     -- 1. independent agent
  2416.     -- 2. char bcp
  2417.  
  2418.     if @allow_dts_id = 1
  2419.     begin
  2420.         if @smid NOT IN ( 1, 4 )
  2421.         begin
  2422.             -- 'The publication has to be in char bcp mode.'
  2423.             raiserror(21172, 16, -1)
  2424.             return(1)
  2425.         end
  2426.         if @independent_agent_id = 0
  2427.         begin
  2428.             -- 'The publication has to be independent agent.'
  2429.             raiserror(21173, 16, -1)
  2430.             return(1)        
  2431.         end
  2432.         if @allow_sync_tran_id = 1 or @allow_queued_tran_id = 1
  2433.         begin
  2434.             raiserror(21180, 16, -1)
  2435.             return(1)
  2436.         end
  2437.     end
  2438.  
  2439.     declare @allow_subscription_copy_id bit
  2440.     IF LOWER(@allow_subscription_copy collate SQL_Latin1_General_CP1_CS_AS) = 'true' SELECT @allow_subscription_copy_id = 1
  2441.     ELSE SELECT @allow_subscription_copy_id = 0
  2442.  
  2443.     -- To allow subscription copy, the publication has to be
  2444.     -- 1. immediate_sync
  2445.     if @allow_subscription_copy_id = 1
  2446.     begin
  2447.         if @immediate_sync_id <> 1
  2448.         begin
  2449.             raiserror(21210, 16, -1)
  2450.             return(1)
  2451.         end
  2452.     end
  2453.  
  2454.     --
  2455.     -- Check parameters for @conflict_policy, @centralized_conflicts, @conflict_retention
  2456.     -- for queued publications
  2457.     --
  2458.     if (@allow_queued_tran_id = 1)
  2459.     begin
  2460.         --
  2461.         -- set default conflict_policy if required
  2462.         --
  2463.         if (@conflict_policy IS NULL)
  2464.         begin
  2465.             --
  2466.             -- if it is snapshot based, then the default policy is 'sub reinit'
  2467.             -- else the default policy is 'pub wins'
  2468.             --
  2469.             select @conflict_policy = case when (@rfid = 1) then 'sub reinit' 
  2470.                                         else 'pub wins' end
  2471.         end
  2472.         
  2473.         if (LOWER(@conflict_policy collate SQL_Latin1_General_CP1_CS_AS) = 'sub reinit')
  2474.             select @conflict_policy_id = 3
  2475.         else if (LOWER(@conflict_policy collate SQL_Latin1_General_CP1_CS_AS) = 'pub wins')
  2476.             select @conflict_policy_id = 1
  2477.         else if (LOWER(@conflict_policy collate SQL_Latin1_General_CP1_CS_AS) = 'sub wins')
  2478.             select @conflict_policy_id = 2
  2479.         else
  2480.         begin
  2481.             raiserror (21184, 16, 2, '@conflict_policy', 'sub reinit', 'pub wins', 'sub wins')
  2482.             return (1)
  2483.         end
  2484.  
  2485.         --
  2486.         -- Check snapshot permissible values
  2487.         --
  2488.         if ((@rfid = 1) and (@conflict_policy_id = 1))
  2489.         begin
  2490.             raiserror (21270, 16, 1, '@conflict_policy', @conflict_policy)
  2491.             return (1)
  2492.         end
  2493.         
  2494.         --
  2495.         -- set default centralized_conflicts if required
  2496.         --
  2497.         if (@centralized_conflicts IS NULL)
  2498.             select @centralized_conflicts = 'true'
  2499.         
  2500.         if (LOWER(@centralized_conflicts collate SQL_Latin1_General_CP1_CS_AS) = 'true')
  2501.             select @centralized_conflicts_bit = 1
  2502.         else if (LOWER(@centralized_conflicts collate SQL_Latin1_General_CP1_CS_AS) = 'false')
  2503.             select @centralized_conflicts_bit = 0
  2504.         else
  2505.         begin
  2506.             raiserror (14148, 16, -1, '@centralized_conflicts')
  2507.             return (1)
  2508.         end
  2509.  
  2510.         --
  2511.         -- Check snapshot permissible values
  2512.         --
  2513.         if ((@rfid = 1) and (@centralized_conflicts_bit = 0))
  2514.         begin
  2515.             raiserror (21270, 16, 1, '@centralized_conflicts', @centralized_conflicts)
  2516.             return (1)
  2517.         end
  2518.         
  2519.         if (@conflict_retention IS NULL)
  2520.             select @conflict_retention = 14
  2521.         else if (@conflict_retention < 0)
  2522.         begin
  2523.             raiserror(20050, 16, -1, 0)
  2524.             return (1)
  2525.         end
  2526.  
  2527.         if ((@queue_type IS NULL) or (LOWER(@queue_type collate SQL_Latin1_General_CP1_CS_AS) = 'sql'))
  2528.             select @queue_type_val = 2
  2529.         else if (LOWER(@queue_type collate SQL_Latin1_General_CP1_CS_AS) = 'msmq')
  2530.             select @queue_type_val = 1
  2531.         else
  2532.         begin
  2533.             raiserror (21184, 16, 3, '@queue_type', 'msmq', 'sql', 'NULL')
  2534.             return (1)
  2535.         end
  2536.     end
  2537.  
  2538.     /*
  2539.     ** Get distribution server information for remote RPC call.
  2540.     */
  2541.     EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  2542.        @distribdb   = @distribdb OUTPUT
  2543.     IF @@ERROR <> 0 or @retcode <> 0
  2544.     BEGIN
  2545.         GOTO UNDO
  2546.     END
  2547.  
  2548.     /*
  2549.     **  Add publication to syspublications.
  2550.     */
  2551.     begin tran
  2552.     save TRAN sp_addpublication
  2553.  
  2554.     select @dbname = db_name()
  2555.     
  2556.     /*
  2557.     ** Construct Log Reader agent name.
  2558.     */
  2559.  
  2560.     declare @job_existing bit
  2561.  
  2562.     -- Create logreader task for the first log based or allow queued publication.
  2563.     -- We need logreader for queued publication to do idenity range management.
  2564.     IF  (@rfid = 0 or @allow_queued_tran_id = 1)  and NOT EXISTS 
  2565.         (SELECT * FROM syspublications where repl_freq = 0 or allow_queued_tran = 1) 
  2566.     BEGIN
  2567.         -- Clear repl dbtable fields. This will avoid unnecessary log scan in the 
  2568.         -- logreader at the first time it runs.
  2569.         --
  2570.         -- sp_droppublication will clear the fields when dropping the last publication, 
  2571.         -- however, it is after the transaction deleting syspublication table being
  2572.         -- committed, thus not guaranteed.
  2573.         -- 
  2574.         -- We also need this logic for upgraded 7.0 databases where we don't clear
  2575.         -- distbackuplsn and distlastlsn fields in unpublishing.
  2576.         --
  2577.         /* ensure we can get in as logreader */
  2578.         exec @retcode = dbo.sp_replflush
  2579.         IF @@ERROR <> 0 or @retcode <> 0
  2580.             GOTO UNDO
  2581.  
  2582.         /* unmark all xacts marked for replication */
  2583.         exec @retcode = dbo.sp_repldone NULL, NULL, 0, 0, 1
  2584.         IF @@ERROR <> 0 or @retcode <> 0
  2585.             GOTO UNDO
  2586.     
  2587.         /* release our hold on the db as logreader */
  2588.         EXEC @retcode = dbo.sp_replflush
  2589.         IF @@ERROR <> 0 or @retcode <> 0
  2590.             GOTO UNDO
  2591.  
  2592.         -- Run checkpoint to make sp_repldone result durable (write repl dbtable fields
  2593.         -- into the checkpoint record).
  2594.         checkpoint
  2595.         IF @@ERROR <> 0
  2596.             GOTO UNDO
  2597.  
  2598.  
  2599.         if @logreader_job_name is null
  2600.             select @job_existing = 0
  2601.         else
  2602.             select @job_existing = 1
  2603.  
  2604.         /*
  2605.         ** Schedule Log Reader agent for the database
  2606.         ** If @logreader_job_name is not null
  2607.         */
  2608.         SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb +'.dbo.sp_MSadd_logreader_agent'
  2609.  
  2610.         EXECUTE @retcode = @distproc
  2611.             @name = @logreader_job_name,
  2612.             @publisher = @@SERVERNAME,
  2613.             @publisher_db = @dbname,
  2614.             @publication = 'ALL',  
  2615.             @local_job = 1,
  2616.             @job_existing = @job_existing 
  2617.  
  2618.         IF @@ERROR <> 0 or @retcode <> 0
  2619.             GOTO UNDO
  2620.     END            
  2621.  
  2622.     INSERT syspublications(description, name, repl_freq,
  2623.                            status, sync_method, snapshot_jobid, independent_agent,
  2624.                            immediate_sync, enabled_for_internet, 
  2625.                            allow_push, allow_pull, allow_anonymous, immediate_sync_ready,
  2626.                            -- SyncTran
  2627.                            allow_sync_tran, autogen_sync_procs, retention, allow_queued_tran,
  2628.                            snapshot_in_defaultfolder, alt_snapshot_folder, pre_snapshot_script, 
  2629.                            post_snapshot_script, compress_snapshot, ftp_address, ftp_port, 
  2630.                            ftp_subdirectory, ftp_login, ftp_password, allow_dts, 
  2631.                            allow_subscription_copy, centralized_conflicts, conflict_retention, 
  2632.                            conflict_policy, queue_type, backward_comp_level)
  2633.  
  2634.     VALUES (@description, @publication, @rfid, @statid, @smid, NULL, 
  2635.             @independent_agent_id, 
  2636.             @immediate_sync_id, @enabled_for_internet_id, @allow_push_id,
  2637.             @allow_pull_id, @allow_anonymous_id, 0,
  2638.             -- SyncTran
  2639.             @allow_sync_tran_id, @autogen_sync_procs_id, @retention, @allow_queued_tran_id,
  2640.             @snapshot_in_defaultfolder_bit, @alt_snapshot_folder, @pre_snapshot_script,
  2641.             @post_snapshot_script, @compress_snapshot_bit, @ftp_address, @ftp_port, 
  2642.             @ftp_subdirectory, @ftp_login, @enc_ftp_password, 
  2643.             @allow_dts_id, @allow_subscription_copy_id, @centralized_conflicts_bit, @conflict_retention, 
  2644.             @conflict_policy_id, @queue_type_val, @backward_comp_level)
  2645.  
  2646.     IF @@ERROR <> 0
  2647.     BEGIN
  2648.         RAISERROR (14018, 16, -1)
  2649.         GOTO UNDO
  2650.     END
  2651.  
  2652.     SELECT @pubid = @@IDENTITY
  2653.  
  2654.     DECLARE @false bit
  2655.     SELECT @false = 0
  2656.  
  2657.     DECLARE @null sysname
  2658.     SELECT @null = NULL
  2659.  
  2660.     /*
  2661.     ** Add the publication to the distributor side
  2662.     */
  2663.     SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  2664.         '.dbo.sp_MSadd_publication'
  2665.     EXECUTE @retcode = @distproc
  2666.     @publisher = @@SERVERNAME,
  2667.     @publisher_db = @dbname,
  2668.     @publication = @publication,
  2669.     @publication_type = @rfid,
  2670.     @independent_agent = @independent_agent_id,
  2671.     @immediate_sync = @immediate_sync_id,
  2672.     @allow_push = @allow_push_id,
  2673.     @allow_pull = @allow_pull_id,
  2674.     @allow_anonymous = @allow_anonymous_id,
  2675.     @snapshot_agent = @null,
  2676.     @logreader_agent = @agentname,
  2677.     @description = @description,
  2678.     @retention = @retention,
  2679.     @sync_method = @smid,
  2680.     @allow_subscription_copy = @allow_subscription_copy_id,
  2681.     @allow_queued_tran = @allow_queued_tran_id,
  2682.     @queue_type = @queue_type_val
  2683.  
  2684.     IF @@ERROR <> 0 or @retcode <> 0
  2685.         BEGIN
  2686.             GOTO UNDO
  2687.         END
  2688.  
  2689.     if @qreader_job_name is not null
  2690.     begin
  2691.         --
  2692.         -- Schedule Queue Reader agent for the database
  2693.         --
  2694.         SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb +'.dbo.sp_MSadd_qreader_agent'
  2695.         EXECUTE @retcode = @distproc @name = @qreader_job_name
  2696.         IF @@ERROR <> 0 or @retcode <> 0
  2697.         GOTO UNDO
  2698.     end    
  2699.  
  2700.     -- Populate the initial list.
  2701.     exec @retcode = dbo.sp_grant_publication_access 
  2702.         @publication = @publication,
  2703.         @login = null,
  2704.         @reserved = 'init'
  2705.     IF @@error <> 0 OR @retcode <> 0
  2706.         GOTO UNDO
  2707.  
  2708.     COMMIT TRAN
  2709.  
  2710.     declare @returnstring nvarchar(512) 
  2711.     set @returnstring = N''
  2712.     if LOWER(@add_to_active_directory collate SQL_Latin1_General_CP1_CS_AS)='true'
  2713.     begin
  2714.         --no error checking needed here.    
  2715.         create table #guid_name_for_active_directory(ad_guidname sysname collate database_default null)
  2716.         if @@ERROR<>0
  2717.         begin
  2718.             goto FAILURE                     
  2719.         end
  2720.         insert into #guid_name_for_active_directory exec @retcode=master.dbo.sp_ActiveDirectory_Obj 'CREATE', 'PUBLICATION', @publication, @dbname
  2721.         if @retcode <> 0 or @@ERROR<>0
  2722.         begin
  2723.             set @returnstring = (select TOP 1 ad_guidname from #guid_name_for_active_directory)
  2724.             goto FAILURE                     
  2725.            end
  2726.         select TOP 1 @ad_guidname = ad_guidname from #guid_name_for_active_directory
  2727.         if @ad_guidname is not NULL
  2728.         begin
  2729.             update syspublications set ad_guidname=@ad_guidname where pubid=@pubid
  2730.             if @@ERROR<>0
  2731.                 goto FAILURE
  2732.         end
  2733.         drop table #guid_name_for_active_directory
  2734.     end
  2735.     RETURN(0)
  2736. FAILURE:
  2737.     drop table #guid_name_for_active_directory
  2738.     if @returnstring is NULL
  2739.         select @returnstring = N''
  2740.     raiserror(21363, 16, -1, @publication, @returnstring)
  2741.     return (1)   
  2742. UNDO:
  2743.     IF @@TRANCOUNT > 0
  2744.     begin
  2745.         ROLLBACK TRAN sp_addpublication
  2746.         COMMIT TRAN   
  2747.     end
  2748.     return 1
  2749. END
  2750. go
  2751.  
  2752. EXEC dbo.sp_MS_marksystemobject sp_addpublication
  2753. GO
  2754.  
  2755. print ''
  2756. print 'Creating procedure sp_changepublication'
  2757. go
  2758.  
  2759. CREATE PROCEDURE sp_changepublication (
  2760.     @publication sysname = NULL,        /* Publication name */
  2761.     @property nvarchar(50) = NULL,           /* The property to change */
  2762.     @value nvarchar(255) = NULL,              /* The new property value */
  2763.     @force_invalidate_snapshot bit = 0,    /* Force invalidate existing snapshot */
  2764.     @force_reinit_subscription bit = 0    /* Force reinit subscription */
  2765. AS
  2766. BEGIN
  2767.     SET NOCOUNT ON
  2768.  
  2769.     /*
  2770.     ** Declarations.
  2771.     */
  2772.  
  2773.     DECLARE @cmd nvarchar(255)
  2774.             ,@cmd2 nvarchar(255)
  2775.             ,@pubid int
  2776.             ,@replfreqid tinyint
  2777.             ,@retcode int
  2778.             ,@statusid tinyint
  2779.             ,@syncmethodid tinyint
  2780.             ,@db_name    sysname
  2781.             ,@distributor sysname
  2782.             ,@distproc nvarchar (255)
  2783.             ,@subscribed int    
  2784.             ,@virtual_id smallint
  2785.             ,@prev_value_bit bit
  2786.             ,@value_bit bit
  2787.             ,@allow_anonymous bit
  2788.             ,@push int
  2789.             ,@pull int
  2790.             ,@independent_agent bit
  2791.             ,@immediate_sync bit
  2792.             ,@distribdb sysname
  2793.             ,@dbname sysname
  2794.             ,@taskid int
  2795.             ,@add_virtual_back bit
  2796.             ,@alt_snapshot_folder nvarchar(255)
  2797.             ,@enabled_for_internet bit
  2798.             ,@ftp_address sysname
  2799.             ,@snapshot_in_defaultfolder bit
  2800.             ,@allow_dts bit
  2801.             ,@in_ActiveD    bit
  2802.             ,@ad_guidname    sysname
  2803.             ,@enc_ftp_password nvarchar(524)
  2804.             ,@conflict_policy_id int
  2805.             ,@centralized_conflicts_bit bit
  2806.             ,@conflict_retention int
  2807.             ,@queue_type int
  2808.             ,@allow_sync_tran bit
  2809.             ,@allow_queued_tran bit
  2810.             
  2811.     SELECT @add_virtual_back = 0
  2812.             ,@push = 0
  2813.             ,@pull = 1
  2814.             ,@alt_snapshot_folder = NULL
  2815.             ,@subscribed = 1
  2816.             ,@virtual_id = -1
  2817.  
  2818.     /*
  2819.     ** Security Check
  2820.     */
  2821.  
  2822.     exec @retcode = dbo.sp_MSreplcheck_publish
  2823.     if @@ERROR <> 0 or @retcode <> 0
  2824.         return(1)
  2825.  
  2826.     /*
  2827.     ** Check to see if the database has been activated for publication.
  2828.     */
  2829.  
  2830.     IF (SELECT category & 1
  2831.           FROM master..sysdatabases
  2832.          WHERE name = DB_NAME() collate database_default) = 0
  2833.  
  2834.     BEGIN
  2835.         RAISERROR (14013, 16, -1)
  2836.         RETURN (1)
  2837.     END
  2838.  
  2839.     select @db_name=db_name()
  2840.     
  2841.     /*
  2842.     ** Parameter Check:  @property.
  2843.     ** If the @property parameter is NULL, print the options.
  2844.     */
  2845.  
  2846.     IF @property IS NULL
  2847.         BEGIN
  2848.             CREATE TABLE #tab1 (properties sysname collate database_default not null)
  2849.             INSERT INTO #tab1 VALUES ('description')
  2850.             --INSERT INTO #tab1 VALUES ('taskid')
  2851.             INSERT INTO #tab1 VALUES ('sync_method')
  2852.             INSERT INTO #tab1 VALUES ('status')
  2853.             INSERT INTO #tab1 VALUES ('repl_freq')
  2854.             INSERT INTO #tab1 VALUES ('independent_agent')
  2855.             INSERT INTO #tab1 VALUES ('immediate_sync')
  2856.             INSERT INTO #tab1 VALUES ('enabled_for_internet')
  2857.             INSERT INTO #tab1 VALUES ('allow_push')
  2858.             INSERT INTO #tab1 VALUES ('allow_pull')
  2859.             INSERT INTO #tab1 VALUES ('allow_anonymous')
  2860.             INSERT INTO #tab1 VALUES ('retention')
  2861.             INSERT INTO #tab1 VALUES ('snapshot_in_defaultfolder')
  2862.             INSERT INTO #tab1 VALUES ('alt_snapshot_folder')
  2863.             INSERT INTO #tab1 VALUES ('pre_snapshot_script')
  2864.             INSERT INTO #tab1 VALUES ('post_snapshot_script')
  2865.             INSERT INTO #tab1 VALUES ('compress_snapshot')
  2866.             INSERT INTO #tab1 VALUES ('ftp_address')
  2867.             INSERT INTO #tab1 VALUES ('ftp_port')
  2868.             INSERT INTO #tab1 VALUES ('ftp_subdirectory')
  2869.             INSERT INTO #tab1 VALUES ('ftp_login')
  2870.             INSERT INTO #tab1 VALUES ('ftp_password')
  2871.             INSERT INTO #tab1 VALUES ('allow_subscription_copy')
  2872.             INSERT INTO #tab1 VALUES ('conflict_policy')
  2873.             INSERT INTO #tab1 VALUES ('centralized_conflicts')
  2874.             INSERT INTO #tab1 VALUES ('conflict_retention')
  2875.             INSERT INTO #tab1 VALUES ('queue_type')
  2876.             INSERT INTO #tab1 VALUES ('publish_to_ActiveDirectory')
  2877.             PRINT ''
  2878.             SELECT * FROM #tab1
  2879.             RETURN (0)
  2880.         END
  2881.  
  2882.     /*
  2883.     ** Parameter Check:  @publication.
  2884.     ** Make sure that the publication exists.
  2885.     */
  2886.  
  2887.     IF @publication IS NULL
  2888.         BEGIN
  2889.             RAISERROR (14043, 16, -1, '@publication')
  2890.             RETURN (1)
  2891.         END
  2892.  
  2893.     EXECUTE @retcode = dbo.sp_validname @publication
  2894.  
  2895.     IF @@ERROR <> 0 OR @retcode <> 0
  2896.     RETURN (1)
  2897.  
  2898.     SELECT @allow_anonymous = allow_anonymous, @pubid = pubid, 
  2899.         @ad_guidname=ad_guidname, --with NULL value if this publication is not in AD
  2900.         @replfreqid = repl_freq,
  2901.         @immediate_sync = immediate_sync,
  2902.         @independent_agent = independent_agent,
  2903.         @syncmethodid = sync_method,
  2904.         @alt_snapshot_folder = alt_snapshot_folder,
  2905.         @enabled_for_internet = enabled_for_internet,
  2906.         @ftp_address = ftp_address,
  2907.         @allow_dts = allow_dts
  2908.         ,@queue_type = queue_type
  2909.         ,@snapshot_in_defaultfolder = snapshot_in_defaultfolder
  2910.         ,@in_ActiveD = case when ad_guidname is NULL then 0 else 1 end 
  2911.         ,@allow_sync_tran = allow_sync_tran
  2912.         ,@allow_queued_tran = allow_queued_tran
  2913.         FROM syspublications 
  2914.         WHERE name = @publication
  2915.  
  2916.     IF @pubid IS NULL
  2917.         BEGIN
  2918.             RAISERROR (20026, 11, -1, @publication)
  2919.             RETURN (1)
  2920.         END
  2921.     ELSE
  2922.  
  2923.     /*
  2924.     ** Parameter Check:  @property.
  2925.     ** Check to make sure that @property is a valid property in
  2926.     ** syspublications.
  2927.     */
  2928.  
  2929.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) NOT IN ( 'taskid','description', 'sync_method',
  2930.      'status', 'repl_freq','immediate_sync', 'independent_agent', 
  2931.      'enabled_for_internet', 'allow_push', 'allow_pull', 'allow_anonymous', 'retention',
  2932.      'snapshot_in_defaultfolder', 'alt_snapshot_folder', 'pre_snapshot_script', 'post_snapshot_script', 
  2933.      'compress_snapshot', 'ftp_address', 'ftp_port', 'ftp_subdirectory',
  2934.      'ftp_login', 'ftp_password','allow_subscription_copy','conflict_policy',
  2935.      'centralized_conflicts','conflict_retention','queue_type','publish_to_activedirectory')
  2936.         BEGIN
  2937.             RAISERROR (21183, 16, -1, @property)
  2938.             RETURN (1)
  2939.         END
  2940.  
  2941.     /*
  2942.     ** Parameter Check:
  2943.     ** If sync_method of the publication is character mode (an indication that it supports
  2944.     ** third party Subscribers), pre/post-snapshot setting must be null   
  2945.     **
  2946.     */
  2947.     IF @syncmethodid = 1 
  2948.     BEGIN
  2949.         IF (LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'pre_snapshot_script' OR
  2950.             LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'post_snapshot_script') AND
  2951.             @value IS NOT NULL AND @value <> ''
  2952.         BEGIN
  2953.             RAISERROR (21151, 16, -1)
  2954.             RETURN (1)
  2955.         END   
  2956.     END
  2957.  
  2958.     /*
  2959.     ** Parameter Check:
  2960.     ** If the Publication's alt_snapshot_folder setting is null, 
  2961.     ** snapshot compression cannot be enabled
  2962.     */
  2963.     IF (@alt_snapshot_folder IS NULL OR @alt_snapshot_folder = '') 
  2964.         AND LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'compress_snapshot'
  2965.         AND LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true'   
  2966.     BEGIN
  2967.         RAISERROR (21157, 16, -1)        
  2968.         RETURN(1)
  2969.     END
  2970.  
  2971.     /* 
  2972.     ** Parameter Check:
  2973.     ** If enabled_for_internet is set to true, the publication must have a non-null
  2974.     ** ftp_address.
  2975.     */
  2976.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'enabled_for_internet' AND
  2977.        LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = N'true' AND 
  2978.        (@ftp_address IS NULL OR @ftp_address = N'')
  2979.     BEGIN
  2980.         RAISERROR(21158, 16, -1)
  2981.         RETURN (1)
  2982.     END
  2983.  
  2984.     /*
  2985.     ** .. and ftp_address cannot be null if the publication is enabled for 
  2986.     ** internet.
  2987.     */
  2988. /*
  2989.     IF @enabled_for_internet = 1 AND
  2990.       (LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'ftp_address'
  2991.         AND (@value IS NULL OR @value = N''))
  2992.     BEGIN
  2993.         RAISERROR(21158, 16, -1)
  2994.         RETURN (1)
  2995.     END
  2996. */
  2997.     /*
  2998.     ** .. and 'alternate snapshot folder' is not null
  2999.     **
  3000.     */
  3001.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'enabled_for_internet' AND
  3002.         LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = N'true' AND
  3003.        (@alt_snapshot_folder IS NULL OR @alt_snapshot_folder = N'')
  3004.     BEGIN
  3005.         RAISERROR(21159, 16, -1)
  3006.         RETURN (1)
  3007.     END 
  3008.  
  3009.     /* 
  3010.     ** Parameter Check:
  3011.     ** If the publication is enabled for internet, the publication must
  3012.     ** have a non-null alternate snapshot folder and the 
  3013.     ** snapshot_in_defaultfolder property must be 0.
  3014.     */
  3015. /*
  3016.     IF @enabled_for_internet = 1 AND 
  3017.        ((LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'alt_snapshot_folder'
  3018.         AND (@value IS NULL OR @value = N'')))
  3019.     BEGIN
  3020.         RAISERROR(21159, 16, -1)
  3021.         RETURN (1)
  3022.     END  
  3023. */
  3024.  
  3025.     /*
  3026.     ** Parameter Check:
  3027.     ** 'ftp_port' cannot be null
  3028.     */
  3029.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'ftp_port' AND @value IS NULL
  3030.     BEGIN
  3031.         RAISERROR (14043, 16, -1, @property)
  3032.         RETURN (1)
  3033.     END
  3034.  
  3035.     -- Check to see if there are snapshot and subscription needs to be reinited.
  3036.     declare @need_new_snapshot bit
  3037.         ,@need_reinit_subscription bit
  3038.         ,@active tinyint
  3039.  
  3040.     select @active = 2
  3041.     select @need_new_snapshot = 0
  3042.     select @need_reinit_subscription = 0
  3043.  
  3044.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) in ('snapshot_in_defaultfolder', 'alt_snapshot_folder',
  3045.         'pre_snapshot_script', 'post_snapshot_script', 'compress_snapshot', 
  3046.         'ftp_address','ftp_port','ftp_subdirectory','ftp_login','ftp_password',
  3047.         'enabled_for_internet')
  3048.     begin
  3049.         select @need_new_snapshot = 1
  3050.     end
  3051.     else if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'sync_method'
  3052.     begin
  3053.         -- If changing to or from concurrent, must reinit subscription.
  3054.         if EXISTS( select * from syspublications sp
  3055.             where sp.pubid = @pubid and 
  3056.             (sp.sync_method in (3,4) or LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) in ('concurrent', 'concurrent_c'))) 
  3057.         BEGIN
  3058.             select @need_new_snapshot = 1
  3059.             select @need_reinit_subscription = 1            
  3060.         END
  3061.         else
  3062.             select @need_new_snapshot = 1
  3063.     end
  3064.     else if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'repl_freq'
  3065.     BEGIN
  3066.         select @need_new_snapshot = 1
  3067.         select @need_reinit_subscription = 1            
  3068.     END
  3069.     
  3070.     -- Have to call this stored procedure to invalidate existing snapshot or reint
  3071.     -- subscriptions if needed
  3072.     EXECUTE @retcode  = dbo.sp_MSreinit_article
  3073.         @publication = @publication, 
  3074.         @need_new_snapshot = @need_new_snapshot,
  3075.         @need_reinit_subscription = @need_reinit_subscription
  3076.         ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  3077.         ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  3078.         ,@check_only = 1
  3079.     IF @@ERROR <> 0 OR @retcode <> 0
  3080.         return (1)
  3081.  
  3082.     /*
  3083.     ** Change the property.
  3084.     */
  3085.     begin tran
  3086.     save TRAN sp_changepublication
  3087.  
  3088.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) ='description'
  3089.         BEGIN
  3090.             UPDATE syspublications SET description = @value
  3091.                 WHERE pubid = @pubid
  3092.             IF @@ERROR <> 0 GOTO UNDO
  3093.         END
  3094.         
  3095.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) ='retention'
  3096.         BEGIN
  3097.             if @value is NULL 
  3098.                 BEGIN
  3099.                     RAISERROR(20081, 16, -1, @property)
  3100.                     GOTO UNDO
  3101.                 END
  3102.                 
  3103.             UPDATE syspublications SET retention = convert(int, @value)
  3104.                 WHERE pubid = @pubid
  3105.             IF @@ERROR <> 0 GOTO UNDO
  3106.         END
  3107.    
  3108.  
  3109.    if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'publish_to_activedirectory'
  3110.            BEGIN
  3111.         if LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  3112.             BEGIN
  3113.                 RAISERROR (14137, 16, -1)
  3114.                 GOTO UNDO
  3115.             END
  3116.  
  3117.         /* Is AD supported? */
  3118.         DECLARE @retval  INT
  3119.         EXECUTE @retval = master.dbo.xp_MSADEnabled
  3120.         if (@retval <> 0)
  3121.         begin
  3122.             RAISERROR(21254, 16, -1, @publication)
  3123.             RETURN (1)
  3124.         end
  3125.  
  3126.            if @in_ActiveD=0 and LOWER(@value collate SQL_Latin1_General_CP1_CS_AS)='true'
  3127.                BEGIN
  3128.                 create table #guid_name_for_active_directory(ad_guidname sysname collate database_default null)
  3129.                 if @@ERROR<>0
  3130.                 begin
  3131.                     raiserror(21363, 16, -1, @publication, N'')
  3132.                     GOTO UNDO                                    
  3133.                 end
  3134.                 insert into #guid_name_for_active_directory exec @retcode=master.dbo.sp_ActiveDirectory_Obj 'CREATE', 'PUBLICATION', @publication, @db_name
  3135.                 if @retcode <> 0 or @@ERROR<>0
  3136.                 begin
  3137.                     declare @errorstring nvarchar(512)
  3138.                     select @errorstring = (select TOP 1 ad_guidname from #guid_name_for_active_directory) 
  3139.                     drop table #guid_name_for_active_directory
  3140.                     if @errorstring is NULL
  3141.                         select @errorstring=N''
  3142.                     raiserror(21363, 16, -1, @publication, @errorstring)
  3143.                     GOTO UNDO                    
  3144.                    end
  3145.                 select TOP 1 @ad_guidname = ad_guidname from #guid_name_for_active_directory
  3146.  
  3147.                 if @ad_guidname is not NULL
  3148.                 begin
  3149.                     update syspublications set ad_guidname=@ad_guidname where pubid=@pubid
  3150.                     if @@ERROR<>0
  3151.                     begin
  3152.                         drop table #guid_name_for_active_directory
  3153.                         raiserror(21363, 16, -1, @publication, N'')
  3154.                         GOTO UNDO                    
  3155.                     end
  3156.                 end
  3157.                 drop table #guid_name_for_active_directory
  3158.                END
  3159.            else if @in_ActiveD=1 and LOWER(@value collate SQL_Latin1_General_CP1_CS_AS)='false'
  3160.                BEGIN
  3161.                 exec @retcode=master.dbo.sp_ActiveDirectory_Obj 'DELETE', 'PUBLICATION', @publication, @db_name, @ad_guidname
  3162.                 if @@ERROR<>0 or @retcode<>0
  3163.                 begin
  3164.                     raiserror(21369, 16, -1, @publication)    
  3165.                     goto UNDO
  3166.                 end
  3167.                 update syspublications set ad_guidname=NULL where pubid=@pubid
  3168.                 if @@ERROR<>0
  3169.                 begin
  3170.                     raiserror(21369, 16, -1, @publication)    
  3171.                     goto UNDO
  3172.                 end
  3173.                END
  3174.        END
  3175.  
  3176.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'taskid'
  3177.        BEGIN
  3178.             -- No longer supported
  3179.             RAISERROR (21023, 16, -1,'@taskid')
  3180.             goto UNDO
  3181.        END
  3182.  
  3183.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'sync_method'
  3184.         BEGIN
  3185.  
  3186.             /*
  3187.             ** Check for a valid synchronization method.
  3188.             */
  3189.  
  3190.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('native', 'character', 'bcp native', 'bcp character', 'concurrent', 'concurrent_c')
  3191.                 BEGIN
  3192.                     RAISERROR (14014, 16, -1)
  3193.                     GOTO UNDO
  3194.                 END
  3195.  
  3196.             /*
  3197.             ** Determine the integer value for the sync_method.
  3198.             */
  3199.  
  3200.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) IN ('native', 'bcp native')
  3201.                 SELECT @syncmethodid = 0
  3202.             ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) IN ('character', 'bcp character')
  3203.                 SELECT @syncmethodid = 1
  3204.             ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) IN ( 'concurrent' )
  3205.                 SELECT @syncmethodid = 3
  3206.             ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) IN ( 'concurrent_c' )
  3207.                 SELECT @syncmethodid = 4
  3208.  
  3209.             if @syncmethodid NOT IN (1,4) and @allow_dts = 1
  3210.             begin
  3211.                 raiserror(21172, 16, -1)
  3212.                 GOTO UNDO
  3213.             end
  3214.  
  3215.             -- Non sql subscribers can only use char bcp (not concurrent)
  3216.             if @syncmethodid <> 1
  3217.             begin
  3218.                 IF EXISTS( select * from syspublications sp, syssubscriptions ss, 
  3219.                             sysarticles sa, master..sysservers srv
  3220.                            where sp.pubid = @pubid 
  3221.                            and sp.pubid = sa.pubid
  3222.                            and sa.artid = ss.artid
  3223.                            and srv.srvid = ss.srvid
  3224.                            and srv.srvproduct = N'MSREPL-NONSQL' collate database_default)
  3225.                 BEGIN
  3226.                     RAISERROR(20593, 16, -1, @publication )
  3227.                     GOTO UNDO
  3228.                 END             
  3229.             end
  3230.  
  3231.             if exists (select * from syspublications where
  3232.                 pubid = @pubid and
  3233.                 sync_method <> @syncmethodid)
  3234.             begin
  3235.                 /*
  3236.                 ** Update the publication with the new synchronization method.
  3237.                 */
  3238.  
  3239.                 /*
  3240.                 ** If we switch to character mode bcp (an indication that this 
  3241.                 ** publication may support non-SQL Server subscribers) for this 
  3242.                 ** publication, the pre/post snapshot commands settings should be
  3243.                 ** nullified  
  3244.                 */    
  3245.                 IF @syncmethodid = 1
  3246.                 BEGIN
  3247.  
  3248.                     UPDATE syspublications 
  3249.                     SET sync_method = @syncmethodid, pre_snapshot_script = NULL,
  3250.                         post_snapshot_script = NULL
  3251.                     WHERE pubid = @pubid
  3252.  
  3253.                 END    
  3254.                 ELSE
  3255.                 BEGIN
  3256.                     UPDATE syspublications
  3257.                        SET sync_method = @syncmethodid
  3258.                      WHERE pubid = @pubid
  3259.                 END
  3260.  
  3261.                 IF @@ERROR <> 0 GOTO UNDO
  3262.             end            
  3263.         END
  3264.  
  3265.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'status'
  3266.         BEGIN
  3267.             
  3268.             /*
  3269.             ** Check to make sure that we have a valid status.
  3270.             */
  3271.  
  3272.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('active', 'inactive')
  3273.                 BEGIN
  3274.                     RAISERROR (14012, 16, -1)
  3275.                     GOTO UNDO
  3276.                 END
  3277.  
  3278.             /*
  3279.             ** Determine the integer value for the status.
  3280.             */
  3281.  
  3282.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'active'
  3283.                 SELECT @statusid = 1
  3284.             ELSE
  3285.                 SELECT @statusid = 0
  3286.  
  3287.             /* If status changed */
  3288.             IF EXISTS (SELECT * FROM syspublications
  3289.                 WHERE  pubid = @pubid  AND
  3290.                  status <> @statusid)
  3291.             BEGIN
  3292.     
  3293.                 /* 
  3294.                 ** If change the status of the publication,
  3295.                 ** virtual anonymous subscription have to be recreated.
  3296.                 **
  3297.                 */
  3298.                 IF @allow_anonymous = 1
  3299.                 BEGIN
  3300.                     /* Drop virtual subscriptions */
  3301.                     EXEC @retcode = dbo.sp_dropsubscription 
  3302.                         @publication = @publication, 
  3303.                         @article = 'all', 
  3304.                         @subscriber = NULL,
  3305.                         @reserved = 'internal'
  3306.                     IF @@ERROR <> 0 OR @retcode <> 0
  3307.                     BEGIN
  3308.                         GOTO UNDO
  3309.                     END
  3310.                 END
  3311.  
  3312.                 /*
  3313.                 ** Update the publication with the new status.
  3314.                 */
  3315.  
  3316.                 UPDATE syspublications
  3317.                    SET status = @statusid
  3318.                  WHERE pubid = @pubid
  3319.  
  3320.                 IF @@ERROR <> 0 
  3321.                 BEGIN
  3322.                     GOTO UNDO                
  3323.                 END
  3324.                 
  3325.                 IF @allow_anonymous = 1
  3326.                     SELECT @add_virtual_back = 1
  3327.             END
  3328.         END
  3329.  
  3330.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'repl_freq'
  3331.         BEGIN
  3332.  
  3333.             /*
  3334.             ** Check for a valid replication frequency value.
  3335.             */
  3336.  
  3337.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('continuous', 'snapshot')
  3338.                 BEGIN
  3339.                     RAISERROR (14015, 16, -1)
  3340.                     GOTO UNDO
  3341.                 END
  3342.  
  3343.  
  3344.             /*
  3345.             ** Determine the integer value for the replication frequency.
  3346.             */
  3347.  
  3348.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'continuous'
  3349.                 SELECT @replfreqid = 0
  3350.             ELSE
  3351.                 SELECT @replfreqid = 1
  3352.  
  3353.             /*
  3354.             ** Only unsubscribed publications may have this modified.
  3355.             */
  3356.             IF EXISTS (SELECT * FROM syssubscriptions s
  3357.                        INNER JOIN sysextendedarticlesview a on s.artid = a.artid
  3358.                         WHERE s.status <> @subscribed
  3359.                           AND s.srvid >= 0 
  3360.                           AND a.pubid = @pubid)
  3361.             BEGIN
  3362.                 RAISERROR (14033, 11, -1)
  3363.                 GOTO UNDO
  3364.             END
  3365.  
  3366.  
  3367.  
  3368. /*
  3369.  
  3370.             IF EXISTS (SELECT * FROM syssubscriptions
  3371.             WHERE 
  3372.                 status <> @subscribed AND
  3373.                 srvid >= 0 AND
  3374.                 artid IN (SELECT artid FROM sysextendedarticlesview where pubid
  3375.                = @pubid))
  3376.             BEGIN
  3377.                 RAISERROR (14033, 11, -1)
  3378.                 GOTO UNDO
  3379.             END
  3380.  
  3381. */
  3382.             IF @immediate_sync = 1
  3383.             BEGIN
  3384.                 /* Drop virtual subscriptions */
  3385.                 EXEC @retcode = dbo.sp_dropsubscription 
  3386.                     @publication = @publication, 
  3387.                     @article = 'all', 
  3388.                     @subscriber = NULL,
  3389.                     @reserved = 'internal'
  3390.                 IF @@ERROR <> 0 OR @retcode <> 0
  3391.                 BEGIN
  3392.                     GOTO UNDO                
  3393.                 END
  3394.             END
  3395.             /*
  3396.             ** Update the publication with the new replication frequency.
  3397.             */
  3398.  
  3399.             UPDATE syspublications
  3400.                SET repl_freq = @replfreqid
  3401.              WHERE pubid = @pubid
  3402.  
  3403.             IF @@ERROR <> 0 
  3404.             BEGIN
  3405.                 GOTO UNDO
  3406.             END
  3407.  
  3408.             IF @immediate_sync = 1
  3409.                 SELECT @add_virtual_back = 1
  3410.         END
  3411.  
  3412.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'alt_snapshot_folder'
  3413.         BEGIN
  3414.             -- If the alt_snapshot_folder is set to '' or NULL,
  3415.             -- set the compress_snapshot bit to 0 and disable
  3416.             -- internet support  
  3417.             IF @value IS NULL OR @value = N''
  3418.             BEGIN
  3419.                 UPDATE syspublications
  3420.                    SET alt_snapshot_folder = @value,
  3421.                        compress_snapshot = 0,
  3422.                        enabled_for_internet = 0
  3423.                  WHERE pubid = @pubid
  3424.             END
  3425.             ELSE
  3426.             BEGIN
  3427.                 UPDATE syspublications
  3428.                    SET alt_snapshot_folder = @value
  3429.                  WHERE pubid = @pubid
  3430.  
  3431.             END
  3432.             IF @@error <> 0
  3433.             BEGIN
  3434.                GOTO UNDO
  3435.             END
  3436.  
  3437.         END
  3438.  
  3439.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'pre_snapshot_script'
  3440.         BEGIN
  3441.             UPDATE syspublications
  3442.                SET pre_snapshot_script = @value
  3443.              WHERE pubid = @pubid
  3444.             IF @@error <> 0
  3445.             BEGIN
  3446.                GOTO UNDO
  3447.             END
  3448.         END
  3449.  
  3450.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'post_snapshot_script'
  3451.         BEGIN
  3452.             UPDATE syspublications
  3453.                SET post_snapshot_script = @value
  3454.              WHERE pubid = @pubid
  3455.             IF @@error <> 0
  3456.             BEGIN
  3457.                GOTO UNDO
  3458.             END
  3459.         END
  3460.  
  3461.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'ftp_address'
  3462.         BEGIN
  3463.     
  3464.             IF @value IS NULL OR @value = N''
  3465.             BEGIN
  3466.                 UPDATE syspublications
  3467.                    SET ftp_address = @value,
  3468.                        enabled_for_internet = 0
  3469.                  WHERE pubid = @pubid
  3470.                 IF @@error <> 0
  3471.                 BEGIN
  3472.                     GOTO UNDO
  3473.                 END
  3474.             END
  3475.             ELSE
  3476.             BEGIN
  3477.                 UPDATE syspublications
  3478.                    SET ftp_address = @value
  3479.                  WHERE pubid = @pubid
  3480.                 IF @@error <> 0
  3481.                 BEGIN
  3482.                     GOTO UNDO
  3483.                 END
  3484.             END
  3485.         END
  3486.             
  3487.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'ftp_port'
  3488.         BEGIN
  3489.             UPDATE syspublications
  3490.                SET ftp_port = CONVERT(int, @value)
  3491.              WHERE pubid = @pubid
  3492.             IF @@error <> 0
  3493.             BEGIN
  3494.                GOTO UNDO
  3495.             END
  3496.         END
  3497.  
  3498.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'ftp_subdirectory'
  3499.         BEGIN
  3500.             UPDATE syspublications
  3501.                SET ftp_subdirectory = @value
  3502.              WHERE pubid = @pubid
  3503.             IF @@error <> 0
  3504.             BEGIN
  3505.                GOTO UNDO
  3506.             END
  3507.         END
  3508.  
  3509.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'ftp_login'
  3510.         BEGIN
  3511.             UPDATE syspublications
  3512.                SET ftp_login = @value
  3513.              WHERE pubid = @pubid
  3514.             IF @@error <> 0
  3515.             BEGIN
  3516.                GOTO UNDO
  3517.             END
  3518.         END
  3519.  
  3520.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = N'ftp_password'
  3521.         BEGIN
  3522.             SELECT @enc_ftp_password = NULL
  3523.             IF @value IS NOT NULL
  3524.             BEGIN
  3525.                 SELECT @enc_ftp_password = @value
  3526.                 EXEC @retcode = master.dbo.xp_repl_encrypt @enc_ftp_password OUTPUT
  3527.                 IF @retcode <> 0
  3528.                 BEGIN
  3529.                     GOTO UNDO
  3530.                 END
  3531.             END
  3532.             UPDATE syspublications
  3533.                SET ftp_password = @enc_ftp_password
  3534.              WHERE pubid = @pubid
  3535.             IF @@error <> 0
  3536.             BEGIN
  3537.                GOTO UNDO
  3538.             END
  3539.         END
  3540.  
  3541.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) IN ('independent_agent', 'immediate_sync','enabled_for_internet',
  3542.             'allow_push', 'allow_pull', 'allow_anonymous', 'snapshot_in_defaultfolder', 
  3543.             'compress_snapshot', 'allow_subscription_copy')
  3544.     BEGIN
  3545.  
  3546.     
  3547.         /*
  3548.         ** Check for a valid  value.
  3549.         */
  3550.  
  3551.         IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  3552.         BEGIN
  3553.             RAISERROR (14137, 16, -1)
  3554.             GOTO UNDO
  3555.         END
  3556.  
  3557.         /*
  3558.         ** set value bit
  3559.         */
  3560.         IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  3561.             SELECT @value_bit = 1
  3562.         ELSE 
  3563.             SELECT @value_bit = 0
  3564.  
  3565.  
  3566.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'independent_agent'
  3567.         BEGIN
  3568.             SELECT @prev_value_bit = independent_agent
  3569.             FROM syspublications 
  3570.             WHERE name = @publication
  3571.  
  3572.             IF @prev_value_bit <> @value_bit
  3573.             BEGIN
  3574.  
  3575.                 IF @immediate_sync = 1 AND @value_bit = 0
  3576.                 BEGIN
  3577.                     RAISERROR (21022, 16, -1)
  3578.                     GOTO UNDO
  3579.                 END    
  3580.  
  3581.             /* 
  3582.             ** no subscriptions are allowed
  3583.             */
  3584.             IF EXISTS (SELECT * FROM syssubscriptions ss, sysextendedarticlesview sa
  3585.                     WHERE ss.artid = sa.artid
  3586.                         AND   sa.pubid = @pubid
  3587.                         AND   ss.srvid <> @virtual_id )
  3588.             BEGIN
  3589.                 RAISERROR (20013, 16, -1, @property)
  3590.                 GOTO UNDO
  3591.             END
  3592.  
  3593.             --
  3594.             -- No share agents for DTS/Updating publications
  3595.             --
  3596.             if (@value_bit = 0 and 
  3597.                 (@allow_dts = 1 or @allow_sync_tran = 1 or @allow_queued_tran = 1))            
  3598.             begin
  3599.                 raiserror(21173, 16, -1)
  3600.                 return(1)
  3601.             end
  3602.  
  3603.             /* Update the publication type */
  3604.             UPDATE syspublications 
  3605.             SET independent_agent = @value_bit
  3606.             WHERE pubid = @pubid
  3607.             IF @@error <> 0
  3608.             BEGIN
  3609.             GOTO UNDO
  3610.             END
  3611.             END
  3612.         END
  3613.  
  3614.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'immediate_sync'
  3615.         BEGIN
  3616.  
  3617.  
  3618.             SELECT @prev_value_bit = immediate_sync
  3619.               FROM syspublications 
  3620.              WHERE name = @publication
  3621.  
  3622.             IF @prev_value_bit <> @value_bit
  3623.             BEGIN
  3624.  
  3625.                IF @independent_agent = 0 AND @value_bit = 1
  3626.                BEGIN
  3627.                     RAISERROR (21022, 16, -1)
  3628.                     GOTO UNDO
  3629.                END    
  3630.  
  3631.                /* 
  3632.                ** The publication has to be immediate_sync type to
  3633.                ** allow anonymous subscriptions
  3634.                */
  3635.                 IF @value_bit = 0 AND
  3636.                     EXISTS (SELECT * FROM syspublications
  3637.                         WHERE pubid = @pubid
  3638.                         AND   allow_anonymous = 1 )
  3639.                 BEGIN
  3640.                     RAISERROR (20011, 16, -1, @property)
  3641.                     GOTO UNDO
  3642.                 END
  3643.  
  3644.             
  3645.                 /* 
  3646.                 ** If turn on immediate_sync, we need to add virtual subscriptions,
  3647.                 ** Otherwise, we need to drop them
  3648.                 ** When adding, we need to change publication bit first
  3649.                 ** When dropping, we need to change publication bit second
  3650.                 */
  3651.                 IF @value_bit = 0
  3652.                 BEGIN
  3653.                     -- Drop virtual subscriptions 
  3654.                     EXEC @retcode = dbo.sp_dropsubscription 
  3655.                         @publication = @publication, 
  3656.                         @article = 'all', 
  3657.                         @subscriber = NULL,
  3658.                         @reserved = 'internal'
  3659.                     IF @@ERROR <> 0 OR @retcode <> 0
  3660.                     BEGIN
  3661.                         GOTO UNDO
  3662.                     END
  3663.  
  3664.                     -- Reset the immediate_sync ready bit
  3665.                     UPDATE syspublications 
  3666.                         SET immediate_sync_ready = 0
  3667.                         WHERE pubid = @pubid
  3668.  
  3669.                 END
  3670.  
  3671.                 /* Update the publication type */
  3672.                 UPDATE syspublications 
  3673.                     SET immediate_sync = @value_bit
  3674.                     WHERE pubid = @pubid
  3675.                 IF @@error <> 0
  3676.                 BEGIN
  3677.                     GOTO UNDO
  3678.                 END
  3679.  
  3680.  
  3681.                 IF @value_bit = 1
  3682.                     SELECT @add_virtual_back = 1
  3683.             END
  3684.         END
  3685.  
  3686.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'allow_anonymous'
  3687.         BEGIN
  3688.  
  3689.             SELECT @prev_value_bit = allow_anonymous
  3690.               FROM syspublications 
  3691.              WHERE name = @publication
  3692.  
  3693.             IF @prev_value_bit <> @value_bit
  3694.             BEGIN
  3695.                 /* 
  3696.                 ** The publication has to be immediate_sync type to
  3697.                 ** allow anonymous subscriptions
  3698.                 */
  3699.                 IF @value_bit = 1 AND
  3700.                     NOT EXISTS (SELECT * FROM syspublications
  3701.                         WHERE pubid = @pubid
  3702.                         AND   immediate_sync = 1 )
  3703.                 BEGIN
  3704.                     RAISERROR (20011, 16, -1, @property)
  3705.                     GOTO UNDO
  3706.                 END
  3707.                 
  3708.                 
  3709.  
  3710.                 /* Drop virtual subscriptions */
  3711.                 EXEC @retcode = dbo.sp_dropsubscription 
  3712.                     @publication = @publication, 
  3713.                     @article = 'all', 
  3714.                     @subscriber = NULL,
  3715.                     @reserved = 'internal'
  3716.                 IF @@ERROR <> 0 OR @retcode <> 0
  3717.                 BEGIN
  3718.                     GOTO UNDO
  3719.                 END
  3720.  
  3721.                 /* Update the publication type */
  3722.                 UPDATE syspublications 
  3723.                     SET allow_anonymous = @value_bit
  3724.                     WHERE pubid = @pubid
  3725.                 IF @@error <> 0
  3726.                 BEGIN
  3727.                    GOTO UNDO
  3728.                 END
  3729.  
  3730.                 /* 
  3731.                 ** add virtual subscriptions back again to enable 
  3732.                 ** anonymous subscription.
  3733.                 */
  3734.                 SELECT @add_virtual_back = 1
  3735.  
  3736.             END
  3737.  
  3738.         END
  3739.  
  3740.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'enabled_for_internet'
  3741.         BEGIN
  3742.  
  3743.             UPDATE syspublications 
  3744.                SET enabled_for_internet = @value_bit
  3745.              WHERE pubid = @pubid
  3746.  
  3747.             IF @@error <> 0
  3748.             BEGIN
  3749.                GOTO UNDO
  3750.             END
  3751.         END
  3752.  
  3753.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'allow_push'
  3754.         BEGIN
  3755.  
  3756.            /* 
  3757.            ** If turn it off, make sure there's no push subscriptions left
  3758.            */
  3759.            IF @value_bit = 0 AND
  3760.             EXISTS (SELECT * FROM syssubscriptions ss, sysextendedarticlesview sa
  3761.                     WHERE ss.artid = sa.artid
  3762.                     AND   sa.pubid = @pubid
  3763.                     AND      ss.subscription_type = @push
  3764.                     AND   ss.srvid <> @virtual_id )
  3765.             BEGIN
  3766.                 RAISERROR (20012, 16, -1)
  3767.                 GOTO UNDO
  3768.             END
  3769.  
  3770.             
  3771.             /* Update the publication type */
  3772.             UPDATE syspublications 
  3773.                 SET allow_push = @value_bit
  3774.                 WHERE pubid = @pubid
  3775.             IF @@error <> 0
  3776.             BEGIN
  3777.                GOTO UNDO
  3778.             END
  3779.         END
  3780.  
  3781.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'allow_pull'
  3782.         BEGIN
  3783.            /* 
  3784.            ** If turn it off, make sure there's no pull subscriptions left
  3785.            */
  3786.            IF @value_bit = 0 AND
  3787.             EXISTS (SELECT * FROM syssubscriptions ss, sysextendedarticlesview sa
  3788.                     WHERE ss.artid = sa.artid
  3789.                     AND   sa.pubid = @pubid
  3790.                     AND      ss.subscription_type = @pull
  3791.                     AND   ss.srvid <> @virtual_id )
  3792.             BEGIN
  3793.                 RAISERROR (20013, 16, -1, @property)
  3794.                 GOTO UNDO
  3795.             END
  3796.             /* Update the publication type */
  3797.             UPDATE syspublications 
  3798.                 SET allow_pull = @value_bit
  3799.                 WHERE pubid = @pubid
  3800.             IF @@error <> 0
  3801.             BEGIN
  3802.                GOTO UNDO
  3803.             END
  3804.         END
  3805.  
  3806.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'snapshot_in_defaultfolder'
  3807.         BEGIN
  3808.             -- snapshot_in_defaultfolder = 1 is only meaningful when
  3809.             -- alt_snapshot_folder is non-null, otherwise 
  3810.             -- a copy of the snapshot files is always kept
  3811.             -- at the publisher's working directory 
  3812.     
  3813.             UPDATE syspublications 
  3814.                SET snapshot_in_defaultfolder = @value_bit
  3815.              WHERE pubid = @pubid
  3816.             IF @@error <> 0
  3817.             BEGIN
  3818.                 GOTO UNDO
  3819.             END
  3820.         END
  3821.  
  3822.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'compress_snapshot'
  3823.         BEGIN
  3824.  
  3825.             UPDATE syspublications
  3826.                SET compress_snapshot = @value_bit
  3827.              WHERE pubid = @pubid
  3828.             IF @@error <> 0
  3829.             BEGIN
  3830.                 GOTO UNDO
  3831.             END
  3832.         END
  3833.  
  3834.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'allow_subscription_copy'
  3835.         BEGIN
  3836.             if @value_bit = 1 and @immediate_sync = 0
  3837.             begin
  3838.                 raiserror(21210, 16, -1)
  3839.                 goto UNDO
  3840.             end
  3841.  
  3842.             UPDATE syspublications
  3843.                SET allow_subscription_copy = @value_bit
  3844.              WHERE pubid = @pubid
  3845.             IF @@error <> 0
  3846.             BEGIN
  3847.                 GOTO UNDO
  3848.             END
  3849.         END
  3850.     END
  3851.  
  3852.     /* Update publication property at the distributor side if necessary */
  3853.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) IN ('description', 'repl_freq', 'independent_agent',
  3854.         'immediate_sync', 'allow_push',
  3855.         'allow_pull', 'allow_anonymous','retention', 'allow_subscription_copy')
  3856.     BEGIN
  3857.         /* Translate the property names and values  */
  3858.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'repl_freq'
  3859.         BEGIN
  3860.             SELECT @property = 'publication_type'
  3861.             SELECT @value = STR(@replfreqid)
  3862.         END
  3863.  
  3864.         /* Translate values */
  3865.         IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  3866.             SELECT @value = '1'
  3867.         ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'false'
  3868.             SELECT @value = '0'
  3869.  
  3870.         /*
  3871.         ** Get distribution server information for remote RPC call.
  3872.         */
  3873.         EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  3874.            @distribdb   = @distribdb OUTPUT
  3875.         IF @@ERROR <> 0 or @retcode <> 0
  3876.             BEGIN
  3877.                 GOTO UNDO
  3878.             END
  3879.  
  3880.         SELECT @dbname =  DB_NAME()
  3881.         
  3882.         SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  3883.             '.dbo.sp_MSchange_publication'
  3884.     
  3885.         EXECUTE @retcode = @distproc
  3886.             @publisher = @@SERVERNAME,
  3887.             @publisher_db = @dbname,
  3888.             @publication = @publication,
  3889.             @property = @property,
  3890.             @value = @value
  3891.  
  3892.         IF @@ERROR <> 0 OR @retcode <> 0
  3893.         BEGIN
  3894.             GOTO UNDO
  3895.         END
  3896.     END
  3897.     
  3898.     IF @add_virtual_back = 1    
  3899.     BEGIN
  3900.         /* Add virtual subscriptions back*/
  3901.         EXEC @retcode = dbo.sp_addsubscription 
  3902.             @publication = @publication, 
  3903.             @article = 'all',
  3904.             @subscriber = NULL,
  3905.             @destination_db = 'virtual',
  3906.             @sync_type = 'automatic',
  3907.             @status = NULL, 
  3908.             @reserved = 'internal'
  3909.         IF @@ERROR <> 0 OR @retcode <> 0
  3910.         BEGIN
  3911.             GOTO UNDO                    
  3912.         END
  3913.     END
  3914.  
  3915.     --
  3916.     -- Queued properties
  3917.     --
  3918.     IF (LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) IN ('conflict_policy', 'centralized_conflicts', 'conflict_retention', 'queue_type'))
  3919.     BEGIN
  3920.         --
  3921.         -- we will consider changes only if the publication supports queued operations
  3922.         --
  3923.         if exists (select * from syspublications 
  3924.                 where pubid = @pubid and allow_queued_tran = 1)
  3925.         BEGIN
  3926.             IF (LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'conflict_policy')
  3927.             BEGIN
  3928.                 if (LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'sub reinit')
  3929.                     select @conflict_policy_id = 3
  3930.                 else if (LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'pub wins')
  3931.                     select @conflict_policy_id = 1
  3932.                 else if (LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'sub wins')
  3933.                     select @conflict_policy_id = 2
  3934.                 else
  3935.                 BEGIN
  3936.                     raiserror (21184, 16, 3, 'conflict_policy', 'sub reinit', 'pub wins', 'sub wins')
  3937.                     GOTO UNDO                    
  3938.                 END
  3939.  
  3940.                 --
  3941.                 -- cannot change this parameter once we have subscriptions
  3942.                 --
  3943.                 IF EXISTS (SELECT * FROM syssubscriptions ss, sysextendedarticlesview sa
  3944.                                 WHERE ss.artid = sa.artid
  3945.                                 AND   sa.pubid = @pubid)
  3946.                 BEGIN
  3947.                     RAISERROR (21268, 16, 1)
  3948.                     GOTO UNDO
  3949.                 END
  3950.  
  3951.                 --
  3952.                 -- Check snapshot permissible values
  3953.                 --
  3954.                 if ((@replfreqid = 1) and (@conflict_policy_id = 1))
  3955.                 begin
  3956.                     raiserror (21270, 16, 1, '@conflict_policy', @value)
  3957.                     GOTO UNDO                    
  3958.                 end
  3959.                 
  3960.                 UPDATE syspublications
  3961.                 SET conflict_policy = @conflict_policy_id
  3962.                 WHERE pubid = @pubid
  3963.                 IF @@error <> 0
  3964.                 BEGIN
  3965.                     GOTO UNDO
  3966.                 END
  3967.             END
  3968.  
  3969.             IF (LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'centralized_conflicts')
  3970.             BEGIN
  3971.                 if (LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true')
  3972.                     select @centralized_conflicts_bit = 1
  3973.                 else if (LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'false')
  3974.                     select @centralized_conflicts_bit = 0
  3975.                 else
  3976.                 begin
  3977.                     raiserror (14148, 16, 3, 'centralized_conflicts')
  3978.                     GOTO UNDO                    
  3979.                 end
  3980.  
  3981.                 --
  3982.                 -- Check snapshot permissible values
  3983.                 --
  3984.                 if ((@replfreqid = 1) and (@centralized_conflicts_bit = 0))
  3985.                 begin
  3986.                     raiserror (21270, 16, 1, '@centralized_conflicts', @value)
  3987.                     GOTO UNDO                    
  3988.                 end
  3989.  
  3990.                 --
  3991.                 -- cannot change this parameter once we have subscriptions
  3992.                 --
  3993.                 IF EXISTS (SELECT * FROM syssubscriptions ss, sysextendedarticlesview sa
  3994.                                 WHERE ss.artid = sa.artid
  3995.                                 AND   sa.pubid = @pubid)
  3996.                 BEGIN
  3997.                     RAISERROR (21268, 16, 2)
  3998.                     GOTO UNDO
  3999.                 END
  4000.  
  4001.                 UPDATE syspublications
  4002.                 SET centralized_conflicts = @centralized_conflicts_bit
  4003.                 WHERE pubid = @pubid
  4004.                 IF @@error <> 0
  4005.                 BEGIN
  4006.                     GOTO UNDO
  4007.                 END
  4008.             END
  4009.  
  4010.             IF (LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'conflict_retention')
  4011.             BEGIN
  4012.                 select @conflict_retention = CAST(@value as integer)
  4013.                 if (@@error != 0) or (@conflict_retention < 0)
  4014.                 BEGIN
  4015.                     raiserror(20050, 16, -1, 0)
  4016.                     GOTO UNDO                    
  4017.                 END
  4018.                 if (@conflict_retention IS NULL)
  4019.                     select @conflict_retention = 60
  4020.  
  4021.                 UPDATE syspublications
  4022.                 SET conflict_retention = @conflict_retention
  4023.                 WHERE pubid = @pubid
  4024.                 IF @@error <> 0
  4025.                 BEGIN
  4026.                     GOTO UNDO
  4027.                 END
  4028.             END
  4029.             
  4030.             IF (LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'queue_type')
  4031.             BEGIN                
  4032.                 IF (CAST(@value as integer) NOT IN (1,2))
  4033.                 BEGIN
  4034.                     RAISERROR(21267, 16, 1, '1,2')
  4035.                     GOTO UNDO
  4036.                 end
  4037.  
  4038.                 IF (CAST(@value as integer) != @queue_type)
  4039.                 BEGIN
  4040.                     select @queue_type = CAST(@value as integer)
  4041.                     IF EXISTS (SELECT * FROM syssubscriptions ss, sysextendedarticlesview sa
  4042.                                     WHERE ss.artid = sa.artid
  4043.                                     AND   sa.pubid = @pubid)
  4044.                     BEGIN
  4045.                         RAISERROR (21268, 16, 3)
  4046.                         GOTO UNDO
  4047.                     END
  4048.  
  4049.                     UPDATE syspublications
  4050.                     SET queue_type = @queue_type
  4051.                     WHERE pubid = @pubid
  4052.                     IF @@error <> 0
  4053.                     BEGIN
  4054.                         GOTO UNDO
  4055.                     END
  4056.  
  4057.                     --
  4058.                     -- For MSMQ queue_type - Check if the distributor supports it
  4059.                     --
  4060.                     if (@queue_type = 1)
  4061.                     begin
  4062.                         EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  4063.                                                 @distribdb   = @distribdb OUTPUT
  4064.                         IF @@ERROR <> 0 or @retcode <> 0
  4065.                         BEGIN
  4066.                             GOTO UNDO
  4067.                         END
  4068.  
  4069.                         SELECT @dbname =  DB_NAME()
  4070.                                 ,@distproc = RTRIM(@distributor) + '.' + @distribdb + 
  4071.                                             N'.dbo.sp_MSchange_publication'
  4072.  
  4073.                         EXECUTE @retcode = @distproc
  4074.                                         @publisher = @@SERVERNAME,
  4075.                                         @publisher_db = @dbname,
  4076.                                         @publication = @publication,
  4077.                                         @property = @property,
  4078.                                         @value = @value
  4079.  
  4080.                         IF @@ERROR <> 0 OR @retcode <> 0
  4081.                         BEGIN
  4082.                             GOTO UNDO
  4083.                         END
  4084.                     end
  4085.                 END
  4086.             END            
  4087.         END
  4088.     END
  4089.  
  4090.     
  4091.     -- Have to call this stored procedure to invalidate existing snapshot or reint
  4092.     -- subscriptions if needed
  4093.     EXECUTE @retcode  = dbo.sp_MSreinit_article
  4094.         @publication = @publication, 
  4095.         @need_new_snapshot = @need_new_snapshot,
  4096.         @need_reinit_subscription = @need_reinit_subscription
  4097.         ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  4098.         ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  4099.     IF @@ERROR <> 0 OR @retcode <> 0
  4100.         GOTO UNDO
  4101.  
  4102.     COMMIT TRAN sp_changepublication
  4103.  
  4104.     --update its registration in active directory
  4105.     if @in_ActiveD=1 and LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) IN ('description','allow_pull', 'allow_anonymous')
  4106.     begin
  4107.         create table #guid_name_for_ADupdate(ad_guidname sysname collate database_default null)
  4108.         if @@ERROR<>0
  4109.         begin
  4110.             goto FAILURE
  4111.         end
  4112.         insert into #guid_name_for_ADupdate exec @retcode = master.dbo.sp_ActiveDirectory_Obj N'UPDATE', N'PUBLICATION', @publication, @db_name, @ad_guidname
  4113.         if @@ERROR<>0 or @retcode<>0
  4114.         begin
  4115.             goto FAILURE                     
  4116.            end
  4117.         select TOP 1 @ad_guidname = ad_guidname from #guid_name_for_ADupdate
  4118.         if @ad_guidname is not NULL
  4119.         begin
  4120.             update syspublications set ad_guidname=@ad_guidname where pubid=@pubid
  4121.             if @@ERROR<>0
  4122.                 goto FAILURE
  4123.         end
  4124.         drop table #guid_name_for_ADupdate
  4125.     end
  4126.  
  4127.     /*
  4128.     ** Return succeed.
  4129.     */
  4130.  
  4131.     RAISERROR (14077, 10, -1)
  4132.     RETURN (0)
  4133. FAILURE:
  4134.     drop table #guid_name_for_ADupdate
  4135.     raiserror(21371, 10, -1, @publication)
  4136.     return (1)   
  4137.  
  4138. UNDO:
  4139.     IF @@TRANCOUNT > 0
  4140.     begin 
  4141.         ROLLBACK TRAN sp_changepublication
  4142.         COMMIT TRAN
  4143.     end
  4144. END
  4145. GO
  4146.  
  4147. EXEC dbo.sp_MS_marksystemobject sp_changepublication
  4148. GO
  4149.  
  4150. print ''
  4151. print 'Creating procedure sp_changesubscription'
  4152. GO
  4153. /* This function should be disallowed */
  4154. CREATE PROCEDURE sp_changesubscription (
  4155.     @publication sysname = NULL,        /* Publication name */
  4156.     @article sysname = NULL,            /* Article name */
  4157.     @subscriber sysname,              /* Subscriber name */
  4158.     @property nvarchar(15) = NULL,           /* The property to change */
  4159.     @value nvarchar(255) = NULL              /* The new property value */
  4160.     ) AS
  4161.  
  4162.     SET NOCOUNT ON
  4163.     RAISERROR (21023, 16, -1,'sp_changesubscription')
  4164.     RETURN(1)
  4165. go
  4166.  
  4167. dump tran master with no_log
  4168. go
  4169.  
  4170. EXEC dbo.sp_MS_marksystemobject sp_changesubscription
  4171. GO
  4172.  
  4173.  
  4174. print ''
  4175. print 'Creating procedure sp_helparticle'
  4176. go
  4177.  
  4178. CREATE PROCEDURE sp_helparticle (
  4179.     @publication sysname,         /* The publication name */
  4180.     @article sysname = '%',       /* The article name */
  4181.     @returnfilter bit = 1         /* Return filter flag */
  4182.     ) AS
  4183.  
  4184.     SET NOCOUNT ON
  4185.  
  4186.     /*
  4187.     ** Declarations.
  4188.     */
  4189.  
  4190.     DECLARE @pubid int
  4191.     DECLARE @retcode int
  4192.     DECLARE @subscriber_bit smallint
  4193.     DECLARE @publish_bit int
  4194.     DECLARE @source_object  sysname
  4195.     DECLARE @source_owner   sysname
  4196.     
  4197.     SELECT @publish_bit = 1
  4198.  
  4199.     /*
  4200.     ** Security Check. To public.
  4201.     
  4202.     */
  4203.     /*
  4204.     ** Check if the database is published.
  4205.     */
  4206.     IF NOT EXISTS (SELECT * FROM master..sysdatabases
  4207.         WHERE name = db_name() collate database_default
  4208.         AND (category & @publish_bit) = @publish_bit)
  4209.         RETURN(0)
  4210.  
  4211.     /*
  4212.     ** Initializations.
  4213.     */
  4214.  
  4215.     SELECT @subscriber_bit = 4
  4216.  
  4217.     IF @publication IS NOT NULL
  4218.         SELECT @pubid = pubid FROM syspublications WHERE name = @publication
  4219.  
  4220.     /*
  4221.     ** Create a temporary table to hold all information.
  4222.     */
  4223.  
  4224.     CREATE TABLE #tab1 (
  4225.         artid               int             NOT NULL,
  4226.         columns             varbinary(32)   NULL,
  4227.         creation_script     nvarchar(255)   collate database_default null,
  4228.         del_cmd             nvarchar(255)   collate database_default null,
  4229.         description         nvarchar(255)   collate database_default null,
  4230.         dest_table          sysname         collate database_default null,
  4231.         old_filter          int             NULL,
  4232.         ins_cmd             nvarchar(255)   collate database_default null,
  4233.         name                sysname         collate database_default not null,
  4234.         objid               int             NOT NULL,
  4235.         pubid               int             NOT NULL,
  4236.         status              tinyint         NOT NULL,
  4237.         sync_objid          int             NULL,
  4238.         type                smallint        NOT NULL,
  4239.         upd_cmd             nvarchar(255)   collate database_default null,
  4240.         source_table        nvarchar(257)   collate database_default null,      /* converted from objid */
  4241.         filter              nvarchar(257)   collate database_default null,      /* converted from old_filter */
  4242.         sync_object         nvarchar(257)   collate database_default null,      /* converted from sync_objid */
  4243.         vpartition          bit             NULL,      /* computed */
  4244.         pre_creation_cmd    tinyint     NOT NULL,
  4245.         filter_clause       ntext           NULL,
  4246.         schema_option       binary(8)       NULL,
  4247.         dest_owner          sysname         collate database_default null,
  4248.         source_owner        sysname         collate database_default null,   /* these two columns are for 7.0 use only */
  4249.         unqua_source_object sysname         collate database_default null,   /* column source_table stays due to backward compatibility */
  4250.         sync_object_owner   sysname         collate database_default null,
  4251.         unqua_sync_object   sysname         collate database_default null,
  4252.         filter_owner        sysname         collate database_default null,
  4253.         unqua_filter        sysname         collate database_default null
  4254.     )
  4255.  
  4256.     CREATE UNIQUE INDEX idx1 ON #tab1 (name, pubid)
  4257.  
  4258.     /*
  4259.     ** Parameter Check:  @publication.
  4260.     ** Check to make sure that there are some articles
  4261.     ** to display.
  4262.     */
  4263.  
  4264.     IF @publication IS NULL
  4265.         BEGIN
  4266.             RAISERROR (14043, 16, -1, '@publication')
  4267.             RETURN (1)
  4268.         END
  4269.  
  4270.     EXECUTE @retcode = dbo.sp_validname @publication
  4271.  
  4272.     IF @retcode <> 0
  4273.     RETURN (1)
  4274.  
  4275.     IF NOT EXISTS (SELECT * FROM syspublications WHERE name = @publication)
  4276.         BEGIN
  4277.             RAISERROR (20026, 11, -1, @publication)
  4278.             RETURN (1)
  4279.         END
  4280.  
  4281.     /*
  4282.     ** Parameter Check:  @article.
  4283.     ** Check to make sure that the article exists, that it conforms
  4284.     ** to the rules for identifiers, and that it isn't NULL.
  4285.     */
  4286.  
  4287.     IF @article IS NULL
  4288.         BEGIN
  4289.             RAISERROR (14043, 16, -1, '@article')
  4290.             RETURN (1)
  4291.         END
  4292.  
  4293.     IF @article <> '%'
  4294.         BEGIN
  4295.  
  4296.             /*
  4297.             EXECUTE @retcode = dbo.sp_validname @article
  4298.  
  4299.             IF @retcode <> 0
  4300.             RETURN (1)
  4301.             */
  4302.  
  4303.             IF NOT EXISTS (SELECT *
  4304.                              FROM sysextendedarticlesview
  4305.                             WHERE name = @article
  4306.                               AND pubid IN (SELECT pubid
  4307.                                               FROM syspublications
  4308.                                              WHERE name = @publication))
  4309.                 BEGIN
  4310.                     RAISERROR (20027, 11, -1, @article)
  4311.                     RETURN (1)
  4312.                 END
  4313.  
  4314.         END
  4315.  
  4316.         
  4317.     IF @returnfilter = 1
  4318.     BEGIN
  4319.         INSERT INTO #tab1 (artid, columns, creation_script, del_cmd,
  4320.                            description, dest_table, old_filter,
  4321.                            ins_cmd, name, objid, pubid, status,
  4322.                            sync_objid, type, upd_cmd, source_table,
  4323.                            filter, vpartition, pre_creation_cmd,
  4324.                filter_clause, schema_option, dest_owner, source_owner, unqua_source_object, 
  4325.                sync_object_owner, unqua_sync_object, filter_owner, unqua_filter)
  4326.                
  4327.          (SELECT artid, columns, creation_script, del_cmd, a.description,
  4328.                  dest_table, filter, ins_cmd, a.name, objid, a.pubid,
  4329.                  a.status, sync_objid, a.type, upd_cmd, NULL, NULL, 0,
  4330.                 a.pre_creation_cmd, a.filter_clause, a.schema_option, a.dest_owner, 
  4331.                 user_name(o.uid), o.name, 
  4332.                 user_name(sync.uid), sync.name,
  4333.                 user_name(fltr.uid), fltr.name
  4334.             FROM syspublications b, 
  4335.                  sysobjects o, 
  4336.                  sysextendedarticlesview a 
  4337.           LEFT JOIN sysobjects sync on a.sync_objid = sync.id
  4338.           LEFT JOIN sysobjects fltr on a.filter = fltr.id
  4339.            WHERE a.name LIKE @article
  4340.              AND a.objid = o.id
  4341.              AND a.pubid = b.pubid
  4342.              AND b.name = @publication)
  4343.     END
  4344.     ELSE
  4345.     BEGIN
  4346.         INSERT INTO #tab1 (artid, columns, creation_script, del_cmd,
  4347.                            description, dest_table, old_filter,
  4348.                            ins_cmd, name, objid, pubid, status,
  4349.                            sync_objid, type, upd_cmd, source_table,
  4350.                            filter, vpartition, pre_creation_cmd,
  4351.                filter_clause, schema_option, dest_owner, source_owner, unqua_source_object, 
  4352.                sync_object_owner, unqua_sync_object, filter_owner, unqua_filter)
  4353.          (SELECT artid, columns, creation_script, del_cmd, a.description,
  4354.                  dest_table, filter, ins_cmd, a.name, objid, a.pubid,
  4355.                  a.status, sync_objid, a.type, upd_cmd, NULL, NULL, 0,
  4356.                  a.pre_creation_cmd, NULL, schema_option, dest_owner, 
  4357.                  user_name(o.uid), o.name,
  4358.                  user_name(sync.uid), sync.name,
  4359.                  user_name(fltr.uid), fltr.name
  4360.            FROM syspublications b, 
  4361.                 sysobjects o, 
  4362.                 sysextendedarticlesview a 
  4363.            LEFT JOIN sysobjects fltr on a.filter = fltr.id
  4364.            LEFT JOIN sysobjects sync on a.sync_objid = sync.id
  4365.            WHERE a.name LIKE @article
  4366.              AND a.objid = o.id
  4367.              AND a.pubid = b.pubid
  4368.              AND b.name = @publication)
  4369.     END
  4370.  
  4371.     UPDATE #tab1
  4372.        SET source_table = QUOTENAME(u.name) + '.' + QUOTENAME(o.name)
  4373.       FROM #tab1, sysobjects o, sysusers u
  4374.      WHERE o.id = #tab1.objid
  4375.        AND o.uid = u.uid
  4376.  
  4377.     UPDATE #tab1
  4378.         SET unqua_sync_object = sysobjects.name
  4379.         from sysobjects 
  4380.         where sysobjects.id = sync_objid
  4381.  
  4382.     UPDATE #tab1
  4383.        SET sync_object = QUOTENAME(sysusers.name) + '.' + QUOTENAME(sysobjects.name)
  4384.       FROM sysobjects, sysusers
  4385.      WHERE sysobjects.id = sync_objid
  4386.        AND sysobjects.uid = sysusers.uid
  4387.  
  4388.     UPDATE #tab1 SET filter = (SELECT sysusers.name + '.' + sysobjects.name
  4389.                                  FROM sysobjects, sysusers
  4390.                                 WHERE sysobjects.id = #tab1.old_filter
  4391.                                   AND sysobjects.uid = sysusers.uid)
  4392.       FROM #tab1
  4393.  
  4394.     DECLARE hC  CURSOR LOCAL FAST_FORWARD FOR SELECT name, pubid FROM #tab1
  4395.     OPEN hC
  4396.     FETCH hC INTO @article, @pubid
  4397.     WHILE (@@fetch_status <> -1)
  4398.         BEGIN
  4399.             IF EXISTS (SELECT *
  4400.                          FROM sysextendedarticlesview a, syscolumns b
  4401.                          WHERE 
  4402.                           ( 
  4403.                            convert(bit, convert( varbinary, substring( convert( nvarchar, a.columns ), 16 - floor((colid-1)/16),1 )) & power( 2, ((colid-1)%16))) = 0
  4404.                            OR convert(bit, convert( varbinary, substring( convert( nvarchar, a.columns ), 16 - floor((colid-1)/16),1 )) & power( 2, ((colid-1)%16))) IS NULL
  4405.                           )
  4406.                           AND a.objid = b.id
  4407.                           AND a.name = @article
  4408.                           AND a.pubid = @pubid)
  4409.  
  4410.                 UPDATE #tab1
  4411.                    SET vpartition = 1
  4412.                  WHERE name = @article
  4413.                    AND pubid = @pubid
  4414.  
  4415.             FETCH hC INTO @article, @pubid
  4416.         END
  4417.     CLOSE hC
  4418.     DEALLOCATE hC
  4419.  
  4420.     SELECT 'article id'                = art.artid,
  4421.        'article name'              = name,
  4422.        'base object'                = source_table,
  4423.        'destination object'         = dest_table,
  4424.        'synchronization object'    = sync_object,
  4425.        'type'                      = case 
  4426.                                         when objectproperty(art.objid, 'IsSchemaBound') = 1 and type <> 0x80 then 0x0100 | convert(smallint, type)
  4427.                                         else type 
  4428.                                      end,    
  4429.        -- bit 32 indicates whether or not timestamp is included in partition for queue publications
  4430.        -- It is internal and should be hidden from DMO scripting, since it is not allowed to 
  4431.        -- be set in sp_addarticle
  4432.        -- sp_helparticlecolumns will use that bit to return proper information.
  4433.        'status'                    = status & ~32,
  4434.        'filter'                    = filter,
  4435.        'description'               = description,
  4436.        'insert_command'            = ins_cmd,
  4437.        'update_command'            = upd_cmd,
  4438.        'delete_command'            = del_cmd,
  4439.        'creation script path'      = creation_script,
  4440.        'vertical partition'        = vpartition,
  4441.        'pre_creation_cmd'       = pre_creation_cmd,
  4442.        -- filter_clause is null when @return_filter is 0
  4443.        'filter_clause'           = filter_clause,
  4444.        'schema_option'            = schema_option,
  4445.        'dest_owner'             = dest_owner,
  4446.        'source_owner'           = source_owner,
  4447.        'unqua_source_object'    = unqua_source_object,
  4448.        'sync_object_owner'      = sync_object_owner,
  4449.        'unqualified_sync_object' = unqua_sync_object,
  4450.        'filter_owner'           = filter_owner,
  4451.        'unqua_filter'           = unqua_filter,
  4452.        'auto_identity_range'    = isnull(artupd.identity_support, 0),
  4453.        'publisher_identity_range' = abs(iden.pub_range),
  4454.        'identity_range'    = abs(iden.range),
  4455.        'threshold' = iden.threshold
  4456.       FROM #tab1 art
  4457.         left join sysarticleupdates artupd on art.artid = artupd.artid
  4458.         left join MSpub_identity_range iden on art.objid = iden.objid
  4459.       ORDER BY 2
  4460.  
  4461.     RETURN (0)
  4462. go
  4463.  
  4464. dump tran master with no_log
  4465. go
  4466.  
  4467. EXEC dbo.sp_MS_marksystemobject sp_helparticle
  4468. GO
  4469.  
  4470.  
  4471. print ''
  4472. print 'Creating procedure sp_MSis_col_replicated'
  4473. go
  4474. create procedure sp_MSis_col_replicated @publication sysname, 
  4475.     @article sysname, 
  4476.     @coltype nvarchar(10) = 'timestamp',  -- identity or timestamp or rowguid
  4477.     @colname sysname = NULL OUTPUT 
  4478. as
  4479.     declare @word tinyint, 
  4480.         @bit tinyint, 
  4481.         @mask binary(2), 
  4482.         @mval int,
  4483.         @colword binary(2), 
  4484.         @columns binary(32),
  4485.         @firstcol tinyint, 
  4486.         @colid smallint,
  4487.         @tabid int,
  4488.         @pubid int
  4489.         
  4490.  
  4491.     select @colname = NULL
  4492.  
  4493.     select @pubid = pubid from syspublications where name = @publication
  4494.  
  4495.     select @tabid = objid from sysarticles 
  4496.         where name = @article and pubid = @pubid
  4497.     
  4498.     if @coltype = 'timestamp'
  4499.     begin
  4500.         if ObjectProperty(@tabid, 'TableHasTimestamp') = 1 
  4501.         begin
  4502.  
  4503.             select @colname = name, @colid = colid from syscolumns 
  4504.                 where id = @tabid and type_name(xtype) = 'timestamp' 
  4505.             
  4506.             if @colname is not NULL
  4507.             begin                       
  4508.                 -- check if  timestamp is replicated
  4509.                 --  Obtain the byte offset and the bit offset, then set the
  4510.                 select @columns=columns from sysarticles where name = @article and pubid = @pubid
  4511.                 select @word = CONVERT(tinyint, 16 - FLOOR((@colid-1)/16))
  4512.                 select @bit = (@colid-1) % 16
  4513.                 select @mval = POWER(2, @bit)
  4514.                 select @mask = convert( binary(2), substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) )                                 
  4515.     
  4516.                 -- Fish out the byte we're interested in and save it in a
  4517.                 -- a temporary local variable.  
  4518.                 select @colword = convert( binary(2), SUBSTRING( convert(nchar(16),@columns), @word, 1) )
  4519.     
  4520.                 if convert( smallint, @colword ) & convert( smallint, @mask) = 0 
  4521.                 begin
  4522.                     select @colname = NULL
  4523.                     return (0)
  4524.                 end
  4525.                 else
  4526.                     return (1)
  4527.             end
  4528.             else
  4529.             begin
  4530.                 select @colname = NULL
  4531.                 return (0)
  4532.             end
  4533.         end
  4534.         else
  4535.         begin
  4536.             select @colname = NULL
  4537.             return (0)
  4538.         end
  4539.     end
  4540.     else if @coltype = 'identity'
  4541.     begin
  4542.         if ObjectProperty(@tabid, 'TableHasIdentity') = 1 
  4543.         begin
  4544.             select @colname = name, @colid = colid from syscolumns 
  4545.             where id = @tabid and ColumnProperty(@tabid, name, 'IsIdentity') = 1
  4546.             
  4547.             if @colname is not NULL
  4548.             begin                       
  4549.                 -- check if column is replicated
  4550.                 --  Obtain the byte offset and the bit offset, then set the
  4551.                 select @columns=columns from sysarticles where name = @article and pubid = @pubid
  4552.                 select @word = CONVERT(tinyint, 16 - FLOOR((@colid-1)/16))
  4553.                 select @bit = (@colid-1) % 16
  4554.                 select @mval = POWER(2, @bit)
  4555.                 select @mask = convert( binary(2), substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) )                                 
  4556.  
  4557.                 -- Fish out the byte we're interested in and save it in a
  4558.                 -- a temporary local variable.  
  4559.                 select @colword = convert( binary(2), SUBSTRING( convert(nchar(16),@columns), @word, 1) )
  4560.                 
  4561.                 if convert( smallint, @colword ) & convert( smallint, @mask) = 0 
  4562.                 begin
  4563.                     select @colname = NULL
  4564.                     return (0)
  4565.                 end
  4566.                 else
  4567.                     return (1)
  4568.             end
  4569.             else
  4570.             begin
  4571.                 select @colname = NULL
  4572.                 return (0)
  4573.             end
  4574.         end
  4575.     end
  4576.     else if @coltype = 'rowguid'
  4577.     begin
  4578.         if ObjectProperty(@tabid, 'TableHasRowGuid') = 1 
  4579.         begin
  4580.             select @colname = name, @colid = colid from syscolumns 
  4581.             where id = @tabid and ColumnProperty(@tabid, name, 'IsRowGuidCol') = 1
  4582.             
  4583.             if @colname is not NULL
  4584.             begin                       
  4585.                 -- check if column is replicated
  4586.                 --  Obtain the byte offset and the bit offset, then set the
  4587.                 select @columns=columns from sysarticles where name = @article and pubid = @pubid
  4588.                 select @word = CONVERT(tinyint, 16 - FLOOR((@colid-1)/16))
  4589.                 select @bit = (@colid-1) % 16
  4590.                 select @mval = POWER(2, @bit)
  4591.                 select @mask = convert( binary(2), substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) )                                 
  4592.  
  4593.                 -- Fish out the byte we're interested in and save it in a
  4594.                 -- a temporary local variable.  
  4595.                 select @colword = convert( binary(2), SUBSTRING( convert(nchar(16),@columns), @word, 1) )
  4596.                 
  4597.                 if convert( smallint, @colword ) & convert( smallint, @mask) = 0 
  4598.                 begin
  4599.                     select @colname = NULL
  4600.                     return (0)
  4601.                 end
  4602.                 else
  4603.                     return (1)
  4604.             end
  4605.             else
  4606.             begin
  4607.                 select @colname = NULL
  4608.                 return (0)
  4609.             end
  4610.         end
  4611.  
  4612.         else
  4613.         begin
  4614.             select @colname = NULL
  4615.             return (0)
  4616.         end
  4617.     end
  4618.     else
  4619.     begin
  4620.         select @colname = NULL
  4621.         return (0)    
  4622.     end
  4623. go
  4624.  
  4625. EXEC dbo.sp_MS_marksystemobject sp_MSis_col_replicated
  4626. GO
  4627.  
  4628. print ''
  4629. print 'Creating procedure sp_articlecolumn'
  4630. go
  4631. CREATE PROCEDURE sp_articlecolumn (
  4632.         @publication sysname,           /* The publication name */
  4633.         @article sysname,               /* The article name */
  4634.         @column sysname = NULL,         /* The column name */
  4635.         @operation nvarchar(4) = N'add'      /* Add or delete a column */
  4636.         -- synctran
  4637.         , @refresh_synctran_procs bit = 1      -- refresh synctran procs or not
  4638.         , @ignore_distributor bit = 0
  4639.         -- DDL
  4640.         , @change_active int = 0
  4641.         , @force_invalidate_snapshot bit = 0    /* Force invalidate existing snapshot */
  4642.         , @force_reinit_subscription bit = 0    /* Force reinit subscription */
  4643.  
  4644.         ) 
  4645. AS
  4646. BEGIN
  4647.  
  4648.     /*
  4649.     ** Declarations.
  4650.     */
  4651.  
  4652.     DECLARE @bit tinyint                /* Bit offset */
  4653.             ,@word tinyint               /* word offset */
  4654.             ,@cnt tinyint, @idx tinyint  /* Loop counter, index */
  4655.             ,@columns binary(32)         /* Temporary storage for the converted column */
  4656.             ,@mask binary(2)              /* Bit mask to set the bit on */
  4657.             ,@mval int
  4658.             ,@newword binary(2)
  4659.             ,@oldword binary(2)
  4660.             ,@pubid int                  /* Publication identification number */
  4661.             ,@retcode int                /* Return code for stored procedures */
  4662.             ,@artid int
  4663.             ,@active tinyint
  4664.             ,@objid int            /* Article base table id */    
  4665.             ,@tablename  sysname
  4666.             ,@fSynctranColChanged bit
  4667.             ,@pkkey sysname
  4668.             ,@indid int
  4669.             ,@index_cnt int
  4670.  
  4671.     select @active = 2
  4672.             ,@fSynctranColChanged = 0
  4673.  
  4674.     /*
  4675.     ** Security Check
  4676.     */
  4677.     exec @retcode = dbo.sp_MSreplcheck_publish
  4678.     if @@ERROR <> 0 or @retcode <> 0
  4679.         return(1)
  4680.  
  4681.     /*
  4682.     ** Check to see if the database has been activated for publication.
  4683.     ** Do not check if @ignore_distributor indicates brute force cleanup.
  4684.     */
  4685.  
  4686.     IF ( (SELECT category & 1
  4687.           FROM master..sysdatabases
  4688.          WHERE name = DB_NAME() collate database_default) = 0 )  and ( @ignore_distributor = 0 )
  4689.  
  4690.     BEGIN
  4691.         RAISERROR (14013, 16, -1)
  4692.         RETURN (1)
  4693.     END
  4694.  
  4695.     /*
  4696.     ** Parameter Check:  @publication.
  4697.     ** Make sure that the publication exists and that it conforms to the
  4698.     ** rules for identifiers.
  4699.     */
  4700.  
  4701.     IF @publication IS NULL
  4702.         BEGIN
  4703.             RAISERROR (14043, 16, -1, N'@publication')
  4704.             RETURN (1)
  4705.         END
  4706.  
  4707.     EXECUTE @retcode = dbo.sp_validname @publication
  4708.  
  4709.     IF @retcode <> 0
  4710.             RETURN (1)
  4711.  
  4712.     declare @allow_queued_tran bit
  4713.     declare @allow_sync_tran bit
  4714.  
  4715.     SELECT @pubid = pubid, 
  4716.         @allow_sync_tran = allow_sync_tran,
  4717.         @allow_queued_tran = allow_queued_tran
  4718.         FROM syspublications WHERE name = @publication
  4719.  
  4720.     IF @pubid IS NULL
  4721.         BEGIN
  4722.             RAISERROR (20026, 11, -1, @publication)
  4723.             RETURN (1)
  4724.         END
  4725.     ELSE
  4726.  
  4727.     /*
  4728.     ** Parameter Check:  @article.
  4729.     ** Check to make sure that the article exists in the publication.
  4730.     */
  4731.  
  4732.     IF @article IS NULL
  4733.         BEGIN
  4734.             RAISERROR (14043, 16, -1, N'@article')
  4735.             RETURN (1)
  4736.         END
  4737.  
  4738.     /*
  4739.     EXECUTE @retcode = dbo.sp_validname @article
  4740.  
  4741.     IF @@ERROR <> 0 OR @retcode <> 0
  4742.     RETURN (1)
  4743.     */
  4744.  
  4745.     /*
  4746.     ** Make sure the article exists.
  4747.     */
  4748.     SELECT @artid = artid FROM sysarticles
  4749.        WHERE pubid = @pubid AND name = @article
  4750.     IF @artid IS NULL
  4751.         BEGIN
  4752.             RAISERROR (20027, 11, -1, @article)
  4753.             RETURN (1)
  4754.         END
  4755.  
  4756.  
  4757.     /*
  4758.     ** Error out if this is a not a table based article
  4759.     */
  4760.     IF NOT EXISTS ( SELECT * FROM sysarticles WHERE artid = @artid
  4761.                       AND pubid = @pubid
  4762.                       AND (type & 1) = 1 )
  4763.         BEGIN
  4764.             RAISERROR (14112, 11, -1 )
  4765.             RETURN (1)
  4766.         END
  4767.  
  4768.     /*
  4769.     ** Parameter Check:  @column.
  4770.     ** Check to make sure that the column exists and conforms to the rules
  4771.     ** for identifiers.
  4772.     */
  4773.  
  4774.     /*
  4775.     IF @column IS NOT NULL
  4776.         BEGIN
  4777.             EXECUTE @retcode = dbo.sp_validname @column
  4778.             IF @@ERROR <> 0 OR @retcode <> 0
  4779.             RETURN (1)
  4780.         END
  4781.     */
  4782.  
  4783.     /*
  4784.     ** Parameter Check:  @operation.
  4785.     ** The operation can be either 'add' or 'drop'.
  4786.     */
  4787.  
  4788.     IF LOWER(@operation collate SQL_Latin1_General_CP1_CS_AS) NOT IN (N'add', N'drop')
  4789.         BEGIN
  4790.             RAISERROR (14019, 16, -1)
  4791.             RETURN (1)
  4792.         END
  4793.         
  4794.     SELECT @objid = (SELECT objid FROM sysarticles WHERE artid = @artid)
  4795.     SELECT @tablename = OBJECT_NAME(@objid)
  4796.    
  4797.     if @column is not null
  4798.     begin
  4799.         declare @colid    smallint
  4800.         select @colid=colid from syscolumns where id=@objid and name=@column
  4801.         if @colid is null
  4802.         begin
  4803.             RAISERROR (14020, 16, -1)
  4804.             RETURN (1)
  4805.         end
  4806.  
  4807.     if LOWER(@operation collate SQL_Latin1_General_CP1_CS_AS) = 'drop'
  4808.     begin        
  4809.         -- Vertical partition is only allowed on table-based article, not IV->table
  4810.             IF OBJECTPROPERTY(@objid, 'IsTable') <> 1
  4811.             BEGIN
  4812.                 RAISERROR (14112, 11, -1 )
  4813.                    RETURN (1)
  4814.             END
  4815.         -- PK column has to be included in vertical partition
  4816.         select @indid = indid from sysindexes where id = @objid and (status & 2048) <> 0    /* PK index */
  4817.         select @index_cnt = 1
  4818.         while (@index_cnt <= 16)
  4819.             begin
  4820.                 select @pkkey = INDEX_COL(@tablename, @indid, @index_cnt)
  4821.                 if @pkkey is NULL
  4822.                     break
  4823.                 if @pkkey=@column
  4824.                     begin
  4825.                         raiserror(21250, 16, -1, @column)
  4826.                         return (1)
  4827.                     end
  4828.                 select @index_cnt = @index_cnt + 1
  4829.             end
  4830.     end
  4831.  
  4832.         -- If the publication is allow_sync_tran, we cannot drop the timestamp
  4833.         -- column from the partition.
  4834.         if (@allow_sync_tran = 1 or @allow_queued_tran = 1) and LOWER(@operation collate SQL_Latin1_General_CP1_CS_AS) = N'drop'
  4835.         begin
  4836.             if N'msrepl_tran_version' = @column
  4837.             BEGIN
  4838.                 RAISERROR (21080, 16, -1)
  4839.                 RETURN (1)
  4840.             END
  4841.         end
  4842.  
  4843.         -- Only columns that have default values can be outside the partition
  4844.         -- Note: do check error if it is schema change.
  4845.         if @change_active = 0 and LOWER(@operation collate SQL_Latin1_General_CP1_CS_AS)=N'drop' and 
  4846.             (@allow_queued_tran = 1 or @allow_sync_tran = 1) and
  4847.             ColumnProperty(@objid, @column, N'IsIdentity') <> 1 and
  4848.             -- 189 is timestamp.
  4849.             not exists (select * from syscolumns where id = @objid and 
  4850.                 name=@column and (isnullable=1 or xtype = 189)) and
  4851.             not exists (select * from sysconstraints where id=@objid and 
  4852.                 colid=@colid and status & 5 = 5)
  4853.         BEGIN
  4854.             RAISERROR(21165, 16, -1, @column)
  4855.             return (1)
  4856.         END
  4857.     end
  4858.  
  4859.     -- @ignore_distributor is set to 1 when removing replication forcefully. In that
  4860.     -- case, no need to check or reinit
  4861.     if @ignore_distributor = 0
  4862.     begin
  4863.         -- Check if there are snapshot or subscriptions and raiserror if needed.
  4864.         EXECUTE @retcode  = dbo.sp_MSreinit_article
  4865.             @publication = @publication, 
  4866.             @article = @article,
  4867.             @need_new_snapshot = 1,
  4868.             @need_reinit_subscription = 1
  4869.             ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  4870.             ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  4871.             ,@check_only = 1
  4872.         IF @@ERROR <> 0 OR @retcode <> 0
  4873.             return (1)
  4874.     end
  4875.  
  4876.     begin tran
  4877.     save TRANSACTION articlecolumn
  4878.  
  4879.     /*
  4880.     ** Make sure that the columns column is not NULL.
  4881.     */
  4882.  
  4883. --    SELECT @zero = 0x00
  4884.  
  4885.     SELECT @columns = columns
  4886.       FROM sysarticles
  4887.      WHERE artid = @artid
  4888.  
  4889.     IF @columns IS NULL
  4890.         UPDATE sysarticles
  4891.            SET columns = 0x00
  4892.          WHERE artid = @artid
  4893.  
  4894.     /*
  4895.     ** If no columns are specified, or if NULL is specified, set all
  4896.     ** the bits in the 'columns' column so all columns will be included.
  4897.     */
  4898.  
  4899.     IF @column IS NULL
  4900.     BEGIN
  4901.        DECLARE hCartcolumn CURSOR LOCAL FAST_FORWARD FOR
  4902.             SELECT name FROM syscolumns where
  4903.                 id = @objid
  4904.     END
  4905.     ELSE
  4906.     BEGIN
  4907.        DECLARE hCartcolumn CURSOR LOCAL FAST_FORWARD FOR 
  4908.             SELECT @column
  4909.     END
  4910.  
  4911.  
  4912.     OPEN hCartcolumn
  4913.  
  4914.     FETCH hCartcolumn INTO @column
  4915.  
  4916.     WHILE (@@fetch_status <> -1)
  4917.     BEGIN
  4918.  
  4919.         DECLARE @columnid smallint   /* Columnid-1 = bit to set */
  4920.         /*
  4921.         ** Get the column id for this column.  We'll use the column id
  4922.         ** to determine the bit in the 'columns' column.  The bit we want
  4923.         ** is equal to the columnid - 1.
  4924.         */
  4925.  
  4926.         SELECT @columnid = colid
  4927.         FROM syscolumns
  4928.         WHERE id = @objid AND name = @column
  4929.  
  4930.         IF ((@@error <> 0) OR (@columnid IS NULL))
  4931.         BEGIN
  4932.             if @@trancount > 0
  4933.             begin
  4934.                 ROLLBACK TRANSACTION articlecolumn
  4935.                 commit tran
  4936.             end
  4937.             RAISERROR (14020, 16, -1)
  4938.             RETURN (1)
  4939.         END
  4940.  
  4941.  
  4942.         if @allow_queued_tran = 1 and 
  4943.         exists (select * from syscolumns WHERE id = @objid and xtype = 189 and name = @column)
  4944.         begin
  4945.             --
  4946.             -- For queued publication, don't mark the timestamp column in the column bitmap
  4947.             -- Refer to sp_helparticlecolumns
  4948.             --
  4949.             IF lower(@operation collate SQL_Latin1_General_CP1_CS_AS) = N'add'
  4950.                 -- Set bit to indicate the timestamp column should be scripted out
  4951.                 -- Also need to set to use explicit column name list at the same time.
  4952.                 update sysarticles set status = (status | 32) | 8  where artid = @artid
  4953.             else
  4954.                 -- Clear the bit
  4955.                 update sysarticles set status = status & ~32 where artid = @artid
  4956.  
  4957.             if @@error <> 0
  4958.             BEGIN
  4959.                 if @@trancount > 0
  4960.                 begin
  4961.                     ROLLBACK TRANSACTION articlecolumn
  4962.                     commit tran
  4963.                 end
  4964.                 RETURN (1)
  4965.             END
  4966.  
  4967.             -- mark for synctran proc refresh
  4968.             select @fSynctranColChanged = 1            
  4969.         end
  4970.         else
  4971.         begin
  4972.  
  4973.             /*
  4974.             ** Obtain the byte offset and the bit offset, then set the
  4975.             ** mask column for the bit we want to turn on.
  4976.             */
  4977.  
  4978.             SELECT @word = CONVERT(tinyint, 16 - FLOOR((@columnid-1)/16))
  4979.             SELECT @bit = (@columnid-1) % 16
  4980.  
  4981.             IF LOWER(@operation collate SQL_Latin1_General_CP1_CS_AS) = N'add'
  4982.                 SELECT @mval = POWER(2, @bit)
  4983.             ELSE
  4984.                 SELECT @mval = ~POWER(2, @bit)
  4985.  
  4986.             select @mask = convert( binary(2), substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) )
  4987.  
  4988.             /*
  4989.             ** Save the columns column in a temporary local variable so we
  4990.             ** can twiddle the bit and then put it back into the table.
  4991.             */
  4992.  
  4993.             SELECT @columns = columns
  4994.             FROM sysarticles
  4995.             WHERE name = @article AND pubid = @pubid
  4996.             if(@change_active = 2) -- Only post if it came from sp_repladd(drop)column
  4997.             begin
  4998.                 exec sp_replpostcmd 0, @pubid, @artid, 51, @columns
  4999.             end
  5000.  
  5001.             /*
  5002.             ** Fish out the byte we're interested in and save it in a
  5003.             ** a temporary local variable.  If it's NULL, just set it
  5004.             ** to 0.  Then apply the bitwise operator OR to twiddle the
  5005.             ** bit in the old byte and save it in another temporary
  5006.             ** local variable @newbyte.
  5007.             */
  5008.             SELECT @oldword = CONVERT( binary(2), SUBSTRING( CONVERT( nvarchar,@columns), @word, 1) )
  5009.  
  5010.             IF @oldword IS NULL SELECT @oldword = 0x0000
  5011.  
  5012.             IF LOWER(@operation collate SQL_Latin1_General_CP1_CS_AS) = N'add'
  5013.                 SELECT @newword = CONVERT(binary(2), convert(smallint, @oldword) | @mask)
  5014.             ELSE
  5015.                 SELECT @newword = CONVERT(binary(2), convert(smallint, @oldword ) & @mask)
  5016.  
  5017.             SELECT @columns = CONVERT(binary(32), STUFF( convert(nchar(16),@columns), @word, 1, convert( nchar(1), @newword)))
  5018.             SELECT @idx = @idx + 1
  5019.  
  5020.             /*
  5021.             ** Update the sysarticles table.  Set the bit appropriately for the selected column
  5022.             */
  5023.  
  5024.             UPDATE sysarticles
  5025.             SET columns = @columns
  5026.             WHERE name = @article
  5027.             AND pubid = @pubid
  5028.  
  5029.             IF @@error <> 0
  5030.             BEGIN
  5031.                 if @@trancount > 0
  5032.                 begin
  5033.                     ROLLBACK TRANSACTION articlecolumn
  5034.                     commit tran
  5035.                 end
  5036.                 RAISERROR (14021, 16, -1)
  5037.                 RETURN (1)
  5038.             END
  5039.  
  5040.             /* 
  5041.             ** if the status has changed, call sp_MSarticlecol to update the publication
  5042.             ** status as appropriate.
  5043.             */
  5044.  
  5045.             IF @oldword != @newword
  5046.             BEGIN
  5047.                 /* Update column published status */
  5048.                 EXECUTE @retcode = dbo.sp_MSarticlecol @artid, @columnid,
  5049.                                         N'publish', @operation
  5050.                 IF (@@error <> 0 OR @retcode <> 0)
  5051.                 BEGIN
  5052.                     if @@trancount > 0
  5053.                     begin
  5054.                         ROLLBACK TRANSACTION articlecolumn
  5055.                         commit tran
  5056.                     end
  5057.                     RAISERROR (14021, 16, -1)
  5058.                     RETURN (1)
  5059.                 END
  5060.                 select @fSynctranColChanged = 1
  5061.             END
  5062.  
  5063.         end -- end of if else block
  5064.  
  5065.         -- fetch the next column
  5066.         FETCH hCartcolumn INTO @column
  5067.  
  5068.     END -- end of while block
  5069.  
  5070.     -- Synctran
  5071.     /*
  5072.     ** If publication is enabled for Synctran and sprocs are auto-generated - regenerate them
  5073.     */
  5074.     declare @autogen_sync_procs_id bit
  5075.         ,@ins_proc_id int, @upd_proc_id int, @del_proc_id int, @upd_trig_id int
  5076.         ,@ins_proc sysname, @upd_proc sysname, @del_proc sysname, @owner sysname, @objname sysname
  5077.         ,@upd_trig sysname
  5078.         ,@sync_pubid int
  5079.         ,@conflict_table_id int, @ins_conflict_proc int
  5080.         ,@cmd nvarchar(4000)
  5081.  
  5082.     select @autogen_sync_procs_id = autogen_sync_procs, @sync_pubid = pubid
  5083.     from syspublications where name = @publication
  5084.  
  5085.     if  @autogen_sync_procs_id = 1 and @refresh_synctran_procs = 1 and @fSynctranColChanged = 1
  5086.     begin
  5087.         -- Drop existing synctran procs
  5088.         select @owner = user_name(OBJECTPROPERTY(objid, N'OwnerId')) from sysarticles a, syspublications p
  5089.         where a.name = @article and
  5090.               p.name = @publication and
  5091.               a.pubid = p.pubid
  5092.  
  5093.         select     @ins_proc_id = sync_ins_proc, 
  5094.                 @upd_proc_id = sync_upd_proc, 
  5095.                 @del_proc_id = sync_del_proc, 
  5096.                 @upd_trig_id = sync_upd_trig,
  5097.                 @conflict_table_id = conflict_tableid,
  5098.                 @ins_conflict_proc = ins_conflict_proc
  5099.         from sysarticleupdates
  5100.             where pubid = @pubid and artid = @artid
  5101.  
  5102.         if @ins_proc_id is not null
  5103.         begin
  5104.             select @objname = object_name(@ins_proc_id)     
  5105.             exec @retcode = dbo.sp_MSdrop_object
  5106.                 @object_name = @objname,
  5107.                 @object_owner = @owner
  5108.             if @@error <> 0 or @retcode <> 0
  5109.                 goto UNDO
  5110.         end
  5111.  
  5112.         if @upd_proc_id is not null
  5113.         begin
  5114.             select @objname = object_name(@upd_proc_id)     
  5115.             exec @retcode = dbo.sp_MSdrop_object
  5116.                 @object_name = @objname,
  5117.                 @object_owner = @owner
  5118.             if @@error <> 0 or @retcode <> 0
  5119.                 goto UNDO
  5120.         end
  5121.  
  5122.         if @del_proc_id is not null
  5123.         begin
  5124.             select @objname = object_name(@del_proc_id)     
  5125.             exec @retcode = dbo.sp_MSdrop_object
  5126.                 @object_name = @objname,
  5127.                 @object_owner = @owner
  5128.             if @@error <> 0 or @retcode <> 0
  5129.                 goto UNDO
  5130.         end
  5131.  
  5132.         if @upd_trig_id is not null
  5133.         begin
  5134.             select @objname = object_name(@upd_trig_id)     
  5135.             exec @retcode = dbo.sp_MSdrop_object
  5136.                 @object_name = @objname,
  5137.                 @object_owner = @owner
  5138.             if @@error <> 0 or @retcode <> 0
  5139.                 goto UNDO
  5140.         end
  5141.  
  5142.         if (@conflict_table_id is not null)
  5143.         begin
  5144.             select @objname = object_name(@conflict_table_id)     
  5145.             exec @retcode = dbo.sp_MSdrop_object
  5146.                 @object_name = @objname,
  5147.                 @object_owner = @owner
  5148.             if (@@error != 0 or @retcode != 0)
  5149.                 goto UNDO
  5150.         end
  5151.  
  5152.         if (@ins_conflict_proc is not null)
  5153.         begin
  5154.             select @objname = object_name(@ins_conflict_proc)     
  5155.             exec @retcode = dbo.sp_MSdrop_object
  5156.                 @object_name = @objname,
  5157.                 @object_owner = @owner
  5158.             if (@@error != 0 or @retcode != 0)
  5159.                 goto UNDO
  5160.         end
  5161.         
  5162.         -- Now generate new ones        
  5163.         select @ins_proc = N'sp_MSsync_ins_' + SUBSTRING(RTRIM(@article), 1, 100) + N'_' + rtrim(convert(varchar, @sync_pubid))
  5164.         select @upd_proc = N'sp_MSsync_upd_' + SUBSTRING(RTRIM(@article), 1, 100) + N'_' + rtrim(convert(varchar, @sync_pubid))
  5165.         select @del_proc = N'sp_MSsync_del_' + SUBSTRING(RTRIM(@article), 1, 100) + N'_' + rtrim(convert(varchar, @sync_pubid))
  5166.         select @upd_trig = N'sp_MSsync_upd_trig_' + SUBSTRING(RTRIM(@article), 1, 100) + N'_' + rtrim(convert(varchar, @sync_pubid))
  5167.  
  5168.         -- check uniqueness of names and revert to ugly guid-based name if friendly name already exists
  5169.         if exists (select name from sysobjects where name in (@ins_proc, @upd_proc, @del_proc))
  5170.         begin
  5171.             declare @guid_name nvarchar(36)
  5172.             select @guid_name =  convert (nvarchar(36), newid())
  5173.             -- remove '-' from guid name because rpc can't handle '-'
  5174.             select @guid_name = replace (@guid_name,N'-',N'_')
  5175.             select @ins_proc = N'sp_MSsync_ins_' + @guid_name
  5176.             select @upd_proc = N'sp_MSsync_upd_' + @guid_name
  5177.             select @del_proc = N'sp_MSsync_del_' + @guid_name
  5178.             select @upd_trig = N'sp_MSsync_upd_trig' + @guid_name
  5179.         end
  5180.  
  5181.         if @ins_proc IS NULL
  5182.         begin
  5183.             RAISERROR (14043, 11, -1, N'@ins_proc')
  5184.             goto UNDO
  5185.         end
  5186.  
  5187.         if @upd_proc IS NULL
  5188.         begin
  5189.             RAISERROR (14043, 11, -1, N'@upd_proc')
  5190.             goto UNDO
  5191.         end
  5192.  
  5193.         if @del_proc IS NULL
  5194.         begin
  5195.             RAISERROR (14043, 11, -1, N'@del_proc')
  5196.             goto UNDO
  5197.         end
  5198.  
  5199.         if @upd_trig IS NULL
  5200.         begin
  5201.             RAISERROR (14043, 11, -1, N'@del_proc')
  5202.             goto UNDO
  5203.         end
  5204.  
  5205.         exec @retcode = dbo.sp_MSgen_sync_tran_procs @publication, @article, @ins_proc, @upd_proc, @del_proc, @upd_trig
  5206.  
  5207.         IF @@ERROR <> 0 OR @retcode <> 0
  5208.             goto UNDO
  5209.  
  5210.         --retrieve sproc id's, fail if they don't exist
  5211.         SELECT @ins_proc_id = id FROM sysobjects WHERE name = @ins_proc
  5212.         SELECT @upd_proc_id = id FROM sysobjects WHERE name = @upd_proc
  5213.         SELECT @del_proc_id = id FROM sysobjects WHERE name = @del_proc
  5214.         SELECT @upd_trig_id = id FROM sysobjects WHERE name = @upd_trig
  5215.  
  5216.         IF (@ins_proc_id IS NULL) OR (@upd_proc_id IS NULL) OR (@del_proc_id IS NULL)
  5217.         BEGIN
  5218.             if @ins_proc_id IS NULL RAISERROR (20500, 16, 1, @ins_proc)
  5219.             if @upd_proc_id IS NULL RAISERROR (20500, 16, 1, @upd_proc)
  5220.             if @del_proc_id IS NULL RAISERROR (20500, 16, 1, @del_proc)
  5221.             if @upd_trig_id IS NULL RAISERROR (20500, 16, 1, @upd_trig)
  5222.             goto UNDO
  5223.         END
  5224.  
  5225.         -- perform update in sysarticleupdates
  5226.         update sysarticleupdates set sync_ins_proc = @ins_proc_id, sync_upd_proc = @upd_proc_id, 
  5227.             sync_del_proc = @del_proc_id,
  5228.             sync_upd_trig = @upd_trig_id
  5229.         where pubid = @pubid and artid = @artid
  5230.         if @@error <> 0
  5231.             goto UNDO
  5232.  
  5233.  
  5234.         --
  5235.         -- create the conflict tran table and table if necessary
  5236.         --
  5237.         if (@allow_queued_tran = 1)
  5238.         begin
  5239.             exec @retcode = dbo.sp_MSmakeconflicttable @article, @publication, 0
  5240.             IF (@@ERROR != 0 OR @retcode != 0)
  5241.                 goto UNDO
  5242.             exec @retcode = dbo.sp_MSmaketrancftproc @article, @publication
  5243.             IF (@@ERROR != 0 OR @retcode != 0)
  5244.                 goto UNDO
  5245.         end 
  5246.         
  5247.         IF @@ERROR <> 0
  5248.         BEGIN
  5249.             RAISERROR (20501, 16, -1)
  5250.             goto UNDO
  5251.          END
  5252.     end
  5253.     -- end synctran
  5254.  
  5255.     -------------------------------------------------------------------
  5256.     -- active article fixups
  5257.     -------------------------------------------------------------------
  5258.  
  5259.     if @change_active<> 0 and @fSynctranColChanged = 1 or
  5260.         -- Besides schema change, we automatically refresh article view if there are 
  5261.         -- subscriptions. We don't refresh the article view otherwise to avoid the view
  5262.         -- being dropped and recreated when adding columns into the partition during
  5263.         -- the creation of the article.
  5264.         exists (select * from syssubscriptions where artid = @artid and
  5265.             srvid >= 0)
  5266.     BEGIN
  5267.         -----------------------------------
  5268.         -- regenerate the article view  
  5269.         -----------------------------------
  5270.  
  5271.         declare @view_name nvarchar(386)
  5272.         declare @filter_clause nvarchar(4000)
  5273.         declare @sync_objid int
  5274.         declare @art_type tinyint
  5275.  
  5276.         select @sync_objid = sa.sync_objid, @filter_clause = sa.filter_clause, @art_type = sa.type
  5277.                              FROM sysarticles sa JOIN syspublications sp ON sa.pubid = sp.pubid
  5278.                              WHERE sa.name = @article 
  5279.                              AND sp.name = @publication
  5280.         -- Only invoke sp_articleview if not manual view and not manual filter
  5281.         if ( @art_type & 0x4 <> 4 and @art_type & 0x2 <> 2 )
  5282.         begin 
  5283.             select @view_name = object_name( @sync_objid )
  5284.  
  5285.             exec @retcode = dbo.sp_articleview @publication = @publication, 
  5286.                                             @article = @article,
  5287.                                             @view_name = @view_name,
  5288.                                             @filter_clause = @filter_clause,
  5289.                                             @change_active = @change_active,
  5290.                                             @force_invalidate_snapshot = @force_invalidate_snapshot,
  5291.                                             @force_reinit_subscription = @force_reinit_subscription
  5292.  
  5293.             IF @@ERROR <> 0 OR @retcode <> 0
  5294.                     goto UNDO
  5295.         end
  5296.     END
  5297.  
  5298.     -- sp_repldropcolumn used @change_active = 2 to prepare, don't invalidate or reinitialize
  5299.     if @change_active <> 2     and
  5300.         -- @ignore_distributor is set to 1 when removing replication forcefully. In that
  5301.         -- case, no need to check or reinit
  5302.         @ignore_distributor = 0
  5303.     begin
  5304.         -- Have to call this stored procedure to invalidate existing snapshot or reint
  5305.         -- subscriptions if needed
  5306.         EXECUTE @retcode  = dbo.sp_MSreinit_article
  5307.             @publication = @publication, 
  5308.             @article = @article,
  5309.             @need_new_snapshot = 1,
  5310.             @need_reinit_subscription = 1
  5311.             ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  5312.             ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  5313.         IF @@ERROR <> 0 OR @retcode <> 0
  5314.             GOTO UNDO
  5315.     end
  5316.  
  5317.     /*
  5318.     ** Force the article cache to be refreshed with the new definition.
  5319.     ** Nothing to flush if brute force cleanup.
  5320.     */
  5321.     if ( @ignore_distributor = 0 )
  5322.         EXECUTE dbo.sp_replflush
  5323.  
  5324.  
  5325.     COMMIT TRANSACTION
  5326. END
  5327. return (0)
  5328. UNDO:
  5329.     if @@trancount > 0
  5330.     begin
  5331.         ROLLBACK TRANSACTION articleview
  5332.         commit tran
  5333.     end
  5334.     RETURN (1)
  5335. go
  5336.  
  5337. EXEC dbo.sp_MS_marksystemobject sp_articlecolumn
  5338. GO
  5339.  
  5340. print ''
  5341. print 'Creating procedure sp_helparticlecolumns'
  5342. go
  5343. CREATE PROCEDURE sp_helparticlecolumns (
  5344.     @publication sysname,            /* The publication name */
  5345.     @article    sysname              /* The article name */
  5346.     ) AS
  5347.  
  5348.     /*
  5349.     ** Declarations.
  5350.     */
  5351.  
  5352.     DECLARE @columns binary(32)
  5353.     DECLARE @pubid int
  5354.     DECLARE @retcode int
  5355.  
  5356.     /*
  5357.     ** Security Check. To public.
  5358.     */
  5359.  
  5360.     /*
  5361.     ** Parameter Check: @article.
  5362.     ** The @article name must conform to the rules for identifiers.
  5363.     */
  5364.  
  5365.     IF @article IS NULL
  5366.         BEGIN
  5367.             RAISERROR (14043, 16, -1, '@article')
  5368.             RETURN (1)
  5369.         END
  5370.     
  5371.     /*
  5372.     EXECUTE @retcode = dbo.sp_validname @article
  5373.  
  5374.     IF @retcode <> 0
  5375.     RETURN (1)
  5376.     */
  5377.  
  5378.     /*
  5379.     ** Parameter Check: @publication.
  5380.     ** The @publication name must conform to the rules for identifiers.
  5381.     */
  5382.  
  5383.     IF @publication IS NULL
  5384.         BEGIN
  5385.             RAISERROR (14043, 16, -1, '@publication')
  5386.             RETURN (1)
  5387.         END
  5388.     
  5389.     EXECUTE @retcode = dbo.sp_validname @publication
  5390.  
  5391.     IF @retcode <> 0
  5392.     RETURN (1)
  5393.     
  5394.     /*
  5395.     ** Get the pubid.
  5396.     */
  5397.  
  5398.     SELECT @pubid = pubid FROM syspublications WHERE name = @publication
  5399.  
  5400.     IF @pubid IS NULL
  5401.         BEGIN
  5402.             RAISERROR (14043, 11, -1, '@pubid')
  5403.             RETURN (1)
  5404.         END
  5405.  
  5406.     /*
  5407.     ** Parameter Check:  @article, @publication.
  5408.     ** Check to make sure that the article exists in this publication.
  5409.     */
  5410.  
  5411.     IF NOT EXISTS (SELECT *
  5412.                      FROM sysextendedarticlesview
  5413.                     WHERE pubid = @pubid
  5414.                       AND name = @article)
  5415.         BEGIN
  5416.             RAISERROR (20027, 11, -1, @article)
  5417.             RETURN (1)
  5418.         END
  5419.  
  5420.  
  5421.     /*
  5422.     ** Error out if this is a not a table based article
  5423.     */
  5424.     IF NOT EXISTS ( SELECT * FROM sysarticles WHERE name = @article
  5425.                           AND pubid = @pubid
  5426.                           AND (type & 1) = 1 )
  5427.         BEGIN
  5428.             RAISERROR (14112, 11, -1 )
  5429.             RETURN (1)
  5430.         END
  5431.  
  5432.     declare @status tinyint
  5433.     declare @objid int
  5434.  
  5435.     SELECT @columns = columns, @status = status, @objid = objid
  5436.       FROM sysarticles
  5437.      WHERE name = @article
  5438.        AND pubid = @pubid
  5439.  
  5440.     -- Get the timestamp column id
  5441.  
  5442.     SELECT 'column id' = colid,
  5443.            'column'    = name,
  5444.            -- 189 is timestamp col
  5445.            -- When the status is set, return timestamp col as published to DMO 
  5446.            -- although it is not in the bitmap used by
  5447.            -- the logreader. Thus, the timestmap will be scripted out and created at the subscriber
  5448.            -- but the value will be generated by subscriber not the logreader.
  5449.            -- 32 is the status bit of keeping timestamp
  5450.            'published' = case xtype when 189
  5451.                 then convert(bit, @status & 32)
  5452.                 else convert(bit, 0) end |
  5453.                 convert(bit, convert( varbinary, substring( convert( nvarchar, @columns ), 16 - floor((colid-1)/16),1 )) & power( 2, ((colid-1)%16)))
  5454.       FROM syscolumns
  5455.      WHERE id = @objid
  5456. go
  5457.  
  5458. EXEC dbo.sp_MS_marksystemobject sp_helparticlecolumns
  5459. GO
  5460.  
  5461. print ''
  5462. print 'Creating procedure sp_helppublication'
  5463. go
  5464.  
  5465.  
  5466. CREATE PROCEDURE sp_helppublication (
  5467.         @publication sysname = '%',     /* The publication name */
  5468.         @found int = 23456 OUTPUT            /* a flag indicate returning row */
  5469.         ) AS
  5470.  
  5471.     SET NOCOUNT ON
  5472.  
  5473.     /*
  5474.     ** Declarations.
  5475.     */
  5476.  
  5477.     DECLARE @pubid      int
  5478.     DECLARE @has_subscription bit
  5479.     DECLARE @retcode int
  5480.     DECLARE @no_row bit
  5481.     DECLARE @publish_bit int
  5482.     
  5483.     SELECT @publish_bit = 1
  5484.     
  5485.     /*
  5486.     ** Check if the database is published.
  5487.     */
  5488.     IF NOT EXISTS (SELECT * FROM master.dbo.sysdatabases
  5489.         WHERE name = db_name() collate database_default
  5490.         AND (category & @publish_bit) = @publish_bit)
  5491.         RETURN(0)
  5492.  
  5493.     /*
  5494.     ** Security Check. To public.
  5495.     */
  5496.  
  5497.     /*
  5498.     ** Initializations.
  5499.     */
  5500.     IF @found = 23456 
  5501.     BEGIN
  5502.         SELECT @no_row=0
  5503.     END
  5504.     ELSE
  5505.     BEGIN
  5506.         SELECT @no_row=1
  5507.     END
  5508.  
  5509.     /*
  5510.     ** Parameter Check:  @publication.
  5511.     ** Check to make sure that there are some publications
  5512.     ** to display.
  5513.     */
  5514.  
  5515.     IF @publication IS NULL
  5516.         BEGIN
  5517.             RAISERROR (14043, 16, -1, '@publication')
  5518.             RETURN (1)
  5519.         END
  5520.     
  5521.     IF @publication <> '%'
  5522.         BEGIN
  5523.             
  5524.             EXECUTE @retcode = dbo.sp_validname @publication
  5525.  
  5526.             IF @retcode <> 0
  5527.             RETURN (1)
  5528.         END
  5529.  
  5530.     IF  NOT EXISTS (SELECT * FROM syspublications
  5531.         WHERE name like @publication)
  5532.  
  5533.     BEGIN
  5534.         SELECT @found = 0
  5535.         RETURN (0) 
  5536.     END
  5537.     ELSE
  5538.     BEGIN
  5539.         SELECT @found = 1
  5540.         IF @no_row <>0
  5541.             RETURN(0)
  5542.     END
  5543.  
  5544.     SELECT 'pubid'                  = pubid,
  5545.            'name'                   = name,
  5546.            'restricted'             = 0,
  5547.            'status'                 = status,
  5548.            -- using 'task' is for backward compatibilty
  5549.            'task'                   = convert(int, 1),
  5550.            'replication frequency'  = repl_freq,
  5551.            'synchronization method' = sync_method,
  5552.            'description'            = description,
  5553.            'immediate_sync'            = immediate_sync,
  5554.            'enabled_for_internet'    = enabled_for_internet,
  5555.            'allow_push'             = allow_push,
  5556.            'allow_pull'             = allow_pull,
  5557.            'allow_anonymous'        = allow_anonymous,
  5558.            'independent_agent'        = independent_agent,
  5559.            'immediate_sync_ready'    = immediate_sync_ready,
  5560.            -- SyncTran
  5561.            'allow_sync_tran'        = allow_sync_tran,
  5562.            'autogen_sync_procs'        = autogen_sync_procs,
  5563.            'snapshot_jobid'         = snapshot_jobid,
  5564.            'retention'              = retention,
  5565.            'has subscription'       = case when EXISTS (select * from syssubscriptions where artid in 
  5566.                                       (select artid from sysextendedarticlesview where pubid = outter.pubid ) )
  5567.                                       then 1 else 0 end,
  5568.            'allow_queued_tran'      = allow_queued_tran,
  5569.            -- Portable snapshot
  5570.            'snapshot_in_defaultfolder'      = snapshot_in_defaultfolder,
  5571.            'alt_snapshot_folder'    = alt_snapshot_folder,
  5572.            -- Pre/post-snapshot commands
  5573.            'pre_snapshot_script'    = pre_snapshot_script,
  5574.            'post_snapshot_script'   = post_snapshot_script,
  5575.            -- Snapshot compression
  5576.            'compress_snapshot'      = compress_snapshot,
  5577.            -- Post 7.0 ftp support
  5578.            'ftp_address'            = ftp_address,
  5579.            'ftp_port'               = ftp_port,
  5580.            'ftp_subdirectory'       = ftp_subdirectory,
  5581.            'ftp_login'              = ftp_login,
  5582.            'allow_dts'                = allow_dts,
  5583.            'allow_subscription_copy'  = allow_subscription_copy,
  5584.            -- 7.5 Queued updates
  5585.            'centralized_conflicts'     = centralized_conflicts, 
  5586.            'conflict_retention'        = conflict_retention, 
  5587.            'conflict_policy'        = conflict_policy,
  5588.            'queue_type'                = queue_type,
  5589.         'backward_comp_level' = backward_comp_level,
  5590.         'publish_to_AD' =        case when ad_guidname is NULL then 0 else 1 end 
  5591.       FROM syspublications outter
  5592.      WHERE name LIKE @publication
  5593.      ORDER BY name
  5594.  
  5595.     RETURN (0)
  5596. go
  5597.  
  5598. EXEC dbo.sp_MS_marksystemobject sp_helppublication
  5599. GO
  5600.  
  5601. -- sp_helppublication_snapshot not used anymore
  5602.  
  5603. print ''
  5604. print 'Creating procedure sp_helpsubscription'
  5605. go
  5606.  
  5607. CREATE PROCEDURE sp_helpsubscription
  5608.     @publication sysname = '%',    /* The publication name */
  5609.     @article sysname = '%',        /* The article name */
  5610.     @subscriber sysname = N'%',      /* The subscriber name */
  5611.     @destination_db sysname = '%',
  5612.     @found int = 23456 OUTPUT
  5613.     AS
  5614.  
  5615.     SET NOCOUNT ON
  5616.  
  5617.     /*
  5618.     ** Declarations.
  5619.     */
  5620.  
  5621.     DECLARE @retcode int
  5622.     DECLARE @subscriber_bit smallint
  5623.     DECLARE @no_row bit
  5624.     DECLARE @srvid smallint
  5625.     DECLARE @pubid int
  5626.     DECLARE @artid int
  5627.     DECLARE @immediate_sync bit
  5628.     DECLARE @subscription_type_id int
  5629.     DECLARE @sync_typeid int
  5630.     DECLARE @publish_bit int
  5631.     DECLARE @orig_publication sysname    
  5632.     DECLARE @full_subscription bit
  5633.  
  5634.     DECLARE @distributor    sysname
  5635.     DECLARE @distributiondb sysname
  5636.     DECLARE @distproc       NVARCHAR(255)
  5637.     DECLARE @dbname         sysname    
  5638.  
  5639.     SELECT @publish_bit = 1
  5640.     SELECT @distributor = NULL
  5641.     SELECT @distributiondb = NULL
  5642.     SELECT @distproc = NULL
  5643.     SELECT @dbname = NULL
  5644.     SELECT @orig_publication = @publication
  5645.  
  5646.     /* Security check. To public. */
  5647.  
  5648.     /*
  5649.     ** Check if the database is published.
  5650.     */
  5651.     IF NOT EXISTS (SELECT * FROM master..sysdatabases
  5652.                     WHERE name = db_name() collate database_default
  5653.                       AND (category & @publish_bit) = @publish_bit)
  5654.         RETURN(0)
  5655.  
  5656.     /*
  5657.     ** Initializations of @now_row.
  5658.     */
  5659.     IF @found = 23456 
  5660.     BEGIN
  5661.         SELECT @no_row=0
  5662.     END
  5663.     ELSE
  5664.     BEGIN
  5665.         SELECT @no_row=1
  5666.     END
  5667.  
  5668.     /*
  5669.     ** Initializations.
  5670.     */
  5671.     SELECT @subscriber_bit = 4
  5672.  
  5673.     /*
  5674.     ** Parameter Check:  @subscriber.
  5675.     */
  5676.     IF @subscriber IS NULL
  5677.         BEGIN
  5678.             RAISERROR (14043, 16, -1, '@subscriber')
  5679.             RETURN (1)
  5680.         END
  5681.  
  5682.     /*
  5683.     ** Parameter Check:  @subscriber.
  5684.     ** Check if remote server is defined as a subscription server, and
  5685.     ** that the name conforms to the rules for identifiers.
  5686.     */
  5687.  
  5688.     IF @subscriber <> '%'
  5689.         BEGIN
  5690.  
  5691.             EXECUTE @retcode = dbo.sp_validname @subscriber
  5692.             select @subscriber = UPPER(@subscriber)
  5693.  
  5694.             IF @retcode <> 0
  5695.         RETURN (1)
  5696.  
  5697.             IF NOT EXISTS (SELECT *
  5698.                              FROM master..sysservers
  5699.                             WHERE UPPER(srvname) = UPPER(@subscriber) collate database_default
  5700.                               AND (srvstatus & @subscriber_bit) <> 0)
  5701.                 BEGIN
  5702.                     RAISERROR (14010, 16, -1)
  5703.                     RETURN (1)
  5704.                 END
  5705.         END
  5706.  
  5707.     /*
  5708.     ** Parameter Check:  @publication.
  5709.     ** If the publication name is specified, check to make sure that it
  5710.     ** conforms to the rules for identifiers and that the publication
  5711.     ** actually exists.  Disallow NULL.
  5712.     */
  5713.  
  5714.     IF @publication IS NULL
  5715.         BEGIN
  5716.             RAISERROR (14043, 16, -1, '@publication')
  5717.             RETURN (1)
  5718.         END
  5719.  
  5720.     IF @publication <> '%'
  5721.         BEGIN
  5722.  
  5723.             EXECUTE @retcode = dbo.sp_validname @publication
  5724.  
  5725.             IF @retcode <> 0
  5726.                 RETURN (1)
  5727.  
  5728.             IF NOT EXISTS (SELECT * FROM syspublications WHERE name = @publication)
  5729.                 BEGIN
  5730.                    RAISERROR (20026, 11, -1, @publication)
  5731.                    RETURN (1)
  5732.                 END
  5733.  
  5734.         END
  5735.  
  5736.     /*
  5737.     ** Parameter Check:  @article.
  5738.     ** If the article name is specified, check to make sure that it
  5739.     ** conforms to the rules for identifiers and that the article
  5740.     ** actually exists.  Disallow NULL.
  5741.     **
  5742.     ** If @article is 'all', only return one entry for the whole publication
  5743.     ** for full subscriptions (subscriptions inlcluding all the articles in a
  5744.     ** publication).
  5745.     ** 
  5746.     */
  5747.  
  5748.     IF @article IS NULL
  5749.         BEGIN
  5750.             RAISERROR (14043, 16, -1, '@article')
  5751.             RETURN (1)
  5752.         END
  5753.  
  5754.     IF LOWER(@article) <> 'all' 
  5755.     BEGIN
  5756.         IF @article <> '%'
  5757.             BEGIN
  5758.                 
  5759.                 /*
  5760.                 EXECUTE @retcode = dbo.sp_validname @article
  5761.  
  5762.                 IF @retcode <> 0
  5763.                 RETURN (1)
  5764.                 */
  5765.  
  5766.                 IF NOT EXISTS (SELECT *
  5767.                                  FROM sysextendedarticlesview
  5768.                                 WHERE name = @article
  5769.                                   AND pubid IN (SELECT pubid
  5770.                                                   FROM syspublications
  5771.                                                  WHERE name LIKE @publication))
  5772.                     BEGIN
  5773.                         RAISERROR (20027, 11, -1, @article)
  5774.                         RETURN (1)
  5775.                     END
  5776.  
  5777.             END
  5778.  
  5779.  
  5780.         IF EXISTS (SELECT * 
  5781.               FROM syssubscriptions sub,
  5782.                    master..sysservers ss,
  5783.                    syspublications pub,
  5784.                    sysextendedarticlesview art
  5785.              WHERE ((@subscriber = N'%') OR (ss.srvname = @subscriber collate database_default))
  5786.                AND sub.srvid = ss.srvid
  5787.                AND pub.name LIKE @publication
  5788.                AND art.name LIKE @article
  5789.                AND art.pubid = pub.pubid
  5790.                AND sub.artid = art.artid
  5791.                AND ((@destination_db = N'%') OR (sub.dest_db = @destination_db))
  5792.                AND (sub.login_name = suser_sname(suser_sid()) OR 
  5793.                     is_srvrolemember('sysadmin') = 1 OR
  5794.                     is_member ('db_owner') = 1)
  5795.                 )
  5796.  
  5797.         BEGIN
  5798.             SELECT @found = 1
  5799.             IF @no_row <> 0 RETURN (0)
  5800.         END
  5801.         ELSE
  5802.         BEGIN
  5803.             SELECT @found = 0
  5804.             RETURN(0)
  5805.         END
  5806.     END
  5807.  
  5808. /*
  5809.         SELECT 'subscriber'           = ss.srvname,
  5810.                'publication'          = pub.name,
  5811.                'article'              = art.name,
  5812.                'destination database' = sub.dest_db,
  5813.                'subscription status'  = sub.status,
  5814.                'synchronization type' = sub.sync_type
  5815.           FROM syssubscriptions sub,
  5816.                master..sysservers ss,
  5817.                syspublications pub,
  5818.                sysextendedarticlesview art
  5819.          WHERE UPPER(ss.srvname) LIKE UPPER(@subscriber) collate database_default
  5820.            AND sub.srvid = ss.srvid
  5821.            AND pub.name LIKE @publication collate database_default
  5822.            AND art.name LIKE @article collate database_default
  5823.            AND art.pubid = pub.pubid
  5824.            AND sub.artid = art.artid
  5825.            AND (sub.login_name = suser_sname(suser_sid()) collate database_default OR 
  5826.                     is_srvrolemember('sysadmin') = 1 OR
  5827.                     is_member ('db_owner') = 1)
  5828.                 )
  5829.          ORDER BY subscriber, publication, article
  5830. */    
  5831.  
  5832.     CREATE TABLE #helpsubscription 
  5833.     (
  5834.     /* Info that will be returned */
  5835.     subscriber sysname collate database_default not null,
  5836.     publication sysname collate database_default not null,
  5837.     article sysname collate database_default not null,
  5838.     destination_db sysname collate database_default not null,
  5839.     status tinyint NOT NULL,
  5840.     sync_type tinyint NOT NULL,
  5841.     subscription_type int NOT NULL,
  5842.     full_subscription bit NOT NULL, /* full subscription or not */
  5843.     distribution_jobid binary(16) NULL,
  5844.     subscription_name nvarchar(255) collate database_default not null,
  5845.     -- SyncTran
  5846.     update_mode int NOT NULL,
  5847.     loopback_detection bit not null
  5848.     )
  5849.  
  5850.  
  5851.     /* Open a CURSOR LOCAL FOR subscriber/destination_db and publication pair 
  5852.     **
  5853.     ** Get subscriptions
  5854.     ** sa or dbo can see every subscriptions while
  5855.     ** others only see their own.
  5856.     */
  5857.  
  5858.     /* 
  5859.     ** Performance Optimization: Eliminate the 'LIKE' clause for publication name.
  5860.     **                           Empirical evidence shows almost 50% speed improvement when
  5861.     **                           opening the cursor if publication name is provided.
  5862.     */
  5863.     IF (@publication <> '%')
  5864.         DECLARE hChelpsubscription_pub CURSOR LOCAL FAST_FORWARD FOR
  5865.             SELECT DISTINCT ss.srvname,
  5866.                    pub.name,
  5867.                    sub.dest_db,
  5868.                    pub.pubid,
  5869.                    sub.srvid,
  5870.                    pub.immediate_sync
  5871.               FROM syssubscriptions sub,
  5872.                    master..sysservers ss,
  5873.                    syspublications pub,
  5874.                    sysextendedarticlesview art
  5875.              WHERE ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber) collate database_default))
  5876.                AND sub.srvid = ss.srvid
  5877.                AND pub.name = @publication collate database_default
  5878.                AND art.pubid = pub.pubid
  5879.                AND sub.artid = art.artid
  5880.                AND ((@destination_db = N'%') OR (sub.dest_db = @destination_db))
  5881.                AND (sub.login_name = suser_sname(suser_sid()) OR 
  5882.                         is_srvrolemember('sysadmin') = 1 OR
  5883.                         is_member ('db_owner') = 1)       
  5884.                FOR READ ONLY
  5885.     ELSE 
  5886.         DECLARE hChelpsubscription_pub CURSOR LOCAL FAST_FORWARD FOR
  5887.             SELECT DISTINCT ss.srvname,
  5888.                    pub.name,
  5889.                    sub.dest_db,
  5890.                    pub.pubid,
  5891.                    sub.srvid,
  5892.                    pub.immediate_sync
  5893.               FROM syssubscriptions sub,
  5894.                    master..sysservers ss,
  5895.                    syspublications pub,
  5896.                    sysextendedarticlesview art
  5897.              WHERE ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber) collate database_default))
  5898.                AND sub.srvid = ss.srvid
  5899.                AND art.pubid = pub.pubid
  5900.                AND sub.artid = art.artid
  5901.                AND ((@destination_db = N'%') OR (sub.dest_db = @destination_db))
  5902.                AND (sub.login_name = suser_sname(suser_sid()) OR 
  5903.                         is_srvrolemember('sysadmin') = 1 OR
  5904.                         is_member ('db_owner') = 1)       
  5905.                FOR READ ONLY
  5906.  
  5907.     OPEN hChelpsubscription_pub
  5908.     FETCH hChelpsubscription_pub INTO @subscriber, @publication, 
  5909.         @destination_db, @pubid, @srvid, @immediate_sync
  5910.         
  5911.     WHILE (@@fetch_status <> -1)
  5912.     BEGIN
  5913.  
  5914.         /* 
  5915.         ** Is it a full subscription ? i.e. Does it include all the articles? 
  5916.         **
  5917.         */
  5918.  
  5919.         IF NOT EXISTS (SELECT * FROM sysextendedarticlesview art WHERE
  5920.                 art.pubid = @pubid and 
  5921.                 NOT EXISTS (SELECT * from syssubscriptions sub WHERE
  5922.                     sub.artid = art.artid and
  5923.                     sub.srvid = @srvid and
  5924.                     sub.dest_db = @destination_db))
  5925.         BEGIN
  5926.             /* Do all the subscriptions on the publication have same
  5927.             ** sync_type and subscription_type ?
  5928.             */
  5929.   
  5930.               /* 
  5931.             ** Get subscription type on the publication
  5932.             */ 
  5933.             SELECT @subscription_type_id = subs.subscription_type,
  5934.                 @sync_typeid = subs.sync_type 
  5935.                 FROM 
  5936.                 sysextendedarticlesview art, syssubscriptions subs  
  5937.                 WHERE
  5938.                 art.pubid = @pubid AND
  5939.                 subs.srvid = @srvid AND
  5940.                 subs.dest_db = @destination_db AND
  5941.                 subs.artid = art.artid
  5942.  
  5943.  
  5944.             /* 
  5945.             ** if the subscription all have the same subscription type
  5946.             ** and sync_type
  5947.             */
  5948.             IF NOT EXISTS (SELECT * from 
  5949.                 sysextendedarticlesview art, syssubscriptions subs where 
  5950.                 art.pubid = @pubid AND
  5951.                 subs.srvid = @srvid AND
  5952.                 subs.dest_db = @destination_db AND
  5953.                 subs.artid = art.artid AND
  5954.                 (subscription_type <> @subscription_type_id OR
  5955.                 sync_type <> @sync_typeid))
  5956.                 
  5957.  
  5958.                 SELECT @full_subscription = 1
  5959.             ELSE
  5960.                 SELECT @full_subscription = 0
  5961.         END
  5962.         ELSE
  5963.         BEGIN
  5964.             SELECT @full_subscription = 0
  5965.         END
  5966.             
  5967.         /* 
  5968.         ** If it is a full subscription and the @article is 'all',
  5969.         ** only return one entry for the whole publication.
  5970.         ** Always return one row per publication if @article is 'ALL'
  5971.         */
  5972.         IF    LOWER(@article) = 'all'
  5973.         BEGIN    
  5974.             INSERT INTO #helpsubscription 
  5975.                 SELECT TOP 1 @subscriber, @publication, @article, @destination_db,
  5976.                     sub.status, sub.sync_type, sub.subscription_type,
  5977.                     @full_subscription, sub.distribution_jobid,
  5978.                     @subscriber + ':' + @destination_db  ,
  5979.                     -- NOTE: For Queued case: we will always return 2/3 for the 4/5 case
  5980.                     -- since we overload update_mode based on queue_type
  5981.                     case     when sub.update_mode = 4 then 2
  5982.                             when sub.update_mode = 5 then 3
  5983.                             else sub.update_mode
  5984.                     end,
  5985.                     sub.loopback_detection
  5986.                     -- end SyncTran
  5987.                     FROM syssubscriptions sub, sysextendedarticlesview art 
  5988.                     WHERE sub.srvid = @srvid AND
  5989.                         sub.dest_db = @destination_db AND
  5990.                         sub.artid = art.artid and
  5991.                         art.pubid = @pubid
  5992.         END
  5993.         ELSE
  5994.         BEGIN
  5995.             /*
  5996.             ** Get subscriptions
  5997.             ** sa or dbo can see every subscriptions while
  5998.             ** others only see their own.
  5999.             */
  6000.  
  6001.             INSERT INTO #helpsubscription 
  6002.                 SELECT    @subscriber, @publication, art.name, @destination_db,
  6003.                     sub.status, sub.sync_type, sub.subscription_type,
  6004.                     @full_subscription, sub.distribution_jobid,
  6005.                     @subscriber + ':' + @destination_db + ':' + art.name,
  6006.                     -- NOTE: For Queued case: we will always return 2/3 for the 4/5 case
  6007.                     -- since we overload update_mode based on queue_type
  6008.                     case     when sub.update_mode = 4 then 2
  6009.                             when sub.update_mode = 5 then 3
  6010.                             else sub.update_mode
  6011.                     end,
  6012.                     sub.loopback_detection
  6013.                     -- end SyncTran
  6014.                     FROM
  6015.                     syssubscriptions sub, sysextendedarticlesview art WHERE
  6016.                         sub.srvid = @srvid AND
  6017.                         sub.dest_db = @destination_db AND
  6018.                         art.pubid = @pubid AND
  6019.                         art.name LIKE @article AND
  6020.                         sub.artid = art.artid AND
  6021.                         (sub.login_name = suser_sname(suser_sid()) OR 
  6022.                          is_srvrolemember('sysadmin') = 1 OR
  6023.                          is_member ('db_owner') = 1)     
  6024.         END
  6025.         FETCH hChelpsubscription_pub INTO @subscriber, @publication, 
  6026.             @destination_db, @pubid, @srvid, @immediate_sync
  6027.     END
  6028.  
  6029.     CLOSE hChelpsubscription_pub
  6030.     DEALLOCATE hChelpsubscription_pub
  6031.  
  6032.     CREATE TABLE #dist_agent_properties
  6033.     (
  6034.         job_id                    VARBINARY(16) NOT NULL,
  6035.         offload_enabled            bit NULL,
  6036.         offload_server            sysname collate database_default null,
  6037.         dts_package_name        sysname collate database_default null,
  6038.         dts_package_location    int NULL,
  6039.         status                    int NULL  
  6040.     )
  6041.  
  6042.     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  6043.                                            @distribdb = @distributiondb OUTPUT
  6044.     IF @retcode <> 0
  6045.         RETURN @retcode
  6046.  
  6047.     SELECT @distributor = RTRIM(@distributor)
  6048.  
  6049.     -- Get distribution agent properties 
  6050.     IF LOWER(@@SERVERNAME) <> LOWER(@distributor)
  6051.     BEGIN
  6052.         SELECT @distproc = @distributor + '.' + @distributiondb + 
  6053.                            '.dbo.sp_MSenumdistributionagentproperties'
  6054.     END    
  6055.     ELSE
  6056.     BEGIN
  6057.         SELECT @distproc = @distributiondb + 
  6058.                            '.dbo.sp_MSenumdistributionagentproperties'
  6059.     END
  6060.  
  6061.     SELECT @dbname = db_name()
  6062.  
  6063.     INSERT INTO #dist_agent_properties
  6064.       EXEC @retcode = @distproc @publisher = @@SERVERNAME, 
  6065.                                 @publisher_db =@dbname, 
  6066.                                 @publication = @orig_publication            
  6067.  
  6068.     /*
  6069.     ** Get subscriptions
  6070.     */
  6071.     SELECT 'subscriber'           = hs.subscriber,
  6072.            'publication'          = hs.publication,
  6073.            'article'              = hs.article,
  6074.            'destination database' = hs.destination_db,
  6075.            'subscription status'  = case
  6076.                 -- distributionstatus = 0 means that the subscription has been deactivated.  
  6077.                 when hs.status = 2 and ap.status = 0 then 0
  6078.                 else hs.status
  6079.                 end,
  6080.            'synchronization type' = hs.sync_type,
  6081.            'subscription type'    = hs.subscription_type,
  6082.            'full subscription'    = hs.full_subscription,
  6083.            'subscription_name'      = hs.subscription_name,
  6084.               -- SyncTran
  6085.            'update mode'          = hs.update_mode,
  6086.            'distribution job id' = hs.distribution_jobid,
  6087.            'loopback_detection'  = hs.loopback_detection,
  6088.            'offload_enabled'     = ap.offload_enabled,
  6089.            'offload_server'      = ap.offload_server,
  6090.            'dts_package_name'    = ap.dts_package_name,
  6091.            'dts_package_location' = ap.dts_package_location
  6092.       FROM #helpsubscription hs
  6093.       LEFT OUTER JOIN #dist_agent_properties ap
  6094.       ON hs.distribution_jobid = ap.job_id  
  6095.       ORDER BY subscriber, publication, article
  6096.  
  6097.     DROP TABLE #dist_agent_properties
  6098. go
  6099.  
  6100. EXEC dbo.sp_MS_marksystemobject sp_helpsubscription
  6101. GO
  6102.  
  6103. print ''
  6104. print 'Creating procedure sp_articlefilter'
  6105. go
  6106. create procedure sp_articlefilter (
  6107.     @publication sysname,           /* publication name */
  6108.     @article sysname,             /* article name */
  6109.     @filter_name nvarchar (386) = NULL,     /* name of filter procedure*/
  6110.     @filter_clause ntext = NULL,               /* article's filter clause */
  6111.     @force_invalidate_snapshot bit = 0,    /* Force invalidate existing snapshot */
  6112.     @force_reinit_subscription bit = 0    /* Force reinit subscription */
  6113. )
  6114. as
  6115. BEGIN
  6116.     declare @pubid smallint
  6117.             ,@table_name sysname
  6118.             ,@user_name sysname
  6119.             ,@qualified_table_name nvarchar (258)
  6120.             ,@filter_id int
  6121.             ,@type tinyint        
  6122.             ,@previous_proc nvarchar(386)
  6123.             ,@retcode int
  6124.             ,@site sysname
  6125.             ,@db sysname
  6126.             ,@owner sysname
  6127.             ,@object nvarchar(386)
  6128.             ,@artid int
  6129.             ,@active tinyint
  6130.             ,@obid int
  6131.             ,@view_id int
  6132.             ,@cmd nvarchar(4000)
  6133.             ,@allow_sync_tran bit
  6134.             ,@allow_queued_tran bit
  6135.  
  6136.     select @active = 2
  6137.  
  6138.     /*
  6139.     ** Security Check.
  6140.     */
  6141.     exec @retcode = dbo.sp_MSreplcheck_publish
  6142.     if @@ERROR <> 0 or @retcode <> 0
  6143.         return(1)
  6144.  
  6145.     /*
  6146.     ** Parameter Check:  @publication.
  6147.     ** Make sure that the publication exists and that it conforms to the
  6148.     ** rules for identifiers.
  6149.     */
  6150.     if @publication is null
  6151.            begin
  6152.               RAISERROR (14043, 16, -1, '@publication')
  6153.               return (1)
  6154.            END
  6155.     
  6156.     execute @retcode = dbo.sp_validname @publication
  6157.     if @retcode <> 0
  6158.     RETURN (1)
  6159.  
  6160.     select @pubid = pubid
  6161.         ,@allow_sync_tran = allow_sync_tran
  6162.         ,@allow_queued_tran = allow_queued_tran
  6163.     from syspublications where name = @publication
  6164.  
  6165.         if @pubid is null
  6166.            begin
  6167.             RAISERROR (20026, 11, -1, @publication)
  6168.             return (1)
  6169.            end
  6170.  
  6171.     /*
  6172.     ** Parameter Check:  @article.
  6173.     ** Check to make sure that the article exists in the publication.
  6174.     */
  6175.  
  6176.     if @article is null
  6177.        begin
  6178.               RAISERROR (14043, 16, -1, '@article')
  6179.               return (1)
  6180.            end
  6181.         /*
  6182.         execute @retcode = dbo.sp_validname @article
  6183.         if @retcode <> 0
  6184.        return (1)
  6185.        */
  6186.  
  6187.     /*
  6188.     ** Get the article information.
  6189.     */
  6190.     select @artid = art.artid, @table_name = so.name, @type = art.type,
  6191.        @filter_id = art.filter, @user_name = USER_NAME(so.uid)
  6192.         ,@view_id = ISNULL(art.sync_objid, art.objid)
  6193.        from sysarticles art, sysobjects so
  6194.        where art.pubid = @pubid
  6195.        and art.name = @article
  6196.        and art.objid = so.id
  6197.  
  6198.     /*
  6199.     ** Fail if there is no article information.
  6200.     */
  6201.     if @artid is null
  6202.        begin
  6203.               RAISERROR (20027, 11, -1, @article)
  6204.               return (1)
  6205.        end
  6206.  
  6207.         /*
  6208.         ** Error out if this is a not a table based article
  6209.         */
  6210.         IF NOT EXISTS ( SELECT * FROM sysarticles WHERE artid = @artid
  6211.                           AND pubid = @pubid
  6212.                           AND (type & 1) = 1 )
  6213.         BEGIN
  6214.             RAISERROR (14112, 11, -1 )
  6215.             RETURN (1)
  6216.         END
  6217.  
  6218.  
  6219.  
  6220.     /*
  6221.     ** Make sure a valid @filter_name was provided and it is
  6222.     ** a valid name.
  6223.     */
  6224.     if datalength(@filter_clause) > 0  
  6225.     begin
  6226.  
  6227.         /*
  6228.         ** Make sure a valid @filter_name was provided and it is
  6229.         ** a valid name.
  6230.         */
  6231.  
  6232.         if @filter_name is null
  6233.         begin
  6234.            RAISERROR (14043, 16, -1, '@filter_name')
  6235.            return (1)
  6236.         end
  6237.         
  6238.         select @object = PARSENAME( @filter_name, 1 )
  6239.         select @owner  = PARSENAME( @filter_name, 2 )
  6240.         select @db     = PARSENAME( @filter_name, 3 )
  6241.         select @site   = PARSENAME( @filter_name, 4 )
  6242.  
  6243.          if @object IS NULL
  6244.                return 1
  6245.  
  6246.         if @owner is NULL
  6247.             select @owner = user_name()
  6248.         select @object = quotename(@owner) + N'.' + quotename(@object)
  6249.     end
  6250.  
  6251.     -- Check if there are snapshot or subscriptions and raiserror if needed.
  6252.     EXECUTE @retcode  = dbo.sp_MSreinit_article
  6253.         @publication = @publication, 
  6254.         @article = @article,
  6255.         @need_new_snapshot = 1,
  6256.         @need_reinit_subscription = 1
  6257.         ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  6258.         ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  6259.         ,@check_only = 1
  6260.     IF @@ERROR <> 0 OR @retcode <> 0
  6261.         return 1
  6262.  
  6263.     begin tran
  6264.     save TRANSACTION articlefilter
  6265.  
  6266.     /*
  6267.     ** If the article has a generated filter (not manually created), then
  6268.     ** drop the current filter before creating the new one.
  6269.     */
  6270.     if ((@type & 0x3) <> 0x3) and @filter_id <> 0
  6271.        begin
  6272.           if exists (select * from sysobjects where id = @filter_id
  6273.                 and type = 'RF')
  6274.          begin
  6275.             exec dbo.sp_MSget_qualified_name @filter_id, @previous_proc output
  6276.             exec ('drop procedure ' + @previous_proc)
  6277.             if @@error <> 0
  6278.                goto UNDO
  6279.          end
  6280.  
  6281.        end
  6282.  
  6283.  
  6284.     /*
  6285.     ** make an owner qualified table name for these operations name
  6286.     */
  6287.  
  6288.     select @qualified_table_name = quotename(@user_name) + '.' + quotename(@table_name)
  6289.  
  6290.     -- Drop replication filter if it exists.
  6291.     -- Note: upgrade needs this logic
  6292.     if datalength(@filter_clause) > 0
  6293.         and exists (select * from sysobjects where id = object_id(@object)
  6294.                 and type = 'RF')
  6295.     begin
  6296.           exec ('drop procedure ' + @object)
  6297.         if @@error <> 0
  6298.            goto UNDO
  6299.     end
  6300.  
  6301.  
  6302.     /*
  6303.     ** If there is a @filter_clause, create the new filter and
  6304.     ** update the article filter id and filter_clause.
  6305.     **/
  6306.     if datalength(@filter_clause) > 0
  6307.        begin
  6308.         declare @subst_clause nvarchar(4000)
  6309.         select @subst_clause = @filter_clause
  6310.  
  6311.         exec @retcode = sp_MSsubst_filter_names @user_name, @table_name, @subst_clause output
  6312.         if @retcode <> 0 or @@error <> 0
  6313.             goto UNDO
  6314.         exec ('create procedure ' + @object +
  6315.             ' for replication as ' +
  6316.             'if exists (select * from ' + @qualified_table_name +
  6317.             ' where ' + @subst_clause +
  6318.             ') return 1 else return 0')
  6319.         if @@error <> 0
  6320.            goto UNDO
  6321.  
  6322.         if (@user_name in ('dbo','INFORMATION_SCHEMA'))
  6323.         begin
  6324.             exec @retcode = dbo.sp_MS_marksystemobject @object
  6325.             if @@error <> 0 
  6326.                 goto UNDO
  6327.         end
  6328.  
  6329.         select @filter_id = id  from sysobjects where id = object_id(@object)
  6330.             and type = 'RF'
  6331.         if @filter_id is null or @filter_id = 0
  6332.            begin
  6333.               RAISERROR (15001, 11, -1, @object)
  6334.               goto UNDO
  6335.            end
  6336.  
  6337.         /*
  6338.         ** Update article
  6339.         */
  6340.         update sysarticles set filter = @filter_id,
  6341.            filter_clause = @filter_clause
  6342.            where pubid = @pubid
  6343.               and name = @article
  6344.         if @@error <> 0
  6345.             goto UNDO
  6346.  
  6347.        -------------------------------------------------------------
  6348.        -- SQL SERVER 7.0 ONLY: update sysobjects, set parent id = underlying
  6349.        -- object id
  6350.        -------------------------------------------------------------
  6351.  
  6352.         select @obid = object_id( @qualified_table_name )
  6353.         EXEC @retcode = dbo.sp_MSsetfilterparent @object, @obid
  6354.         if @retcode <> 0 or @@error <> 0
  6355.             goto UNDO
  6356.         EXEC @retcode = dbo.sp_MSsetfilteredstatus @obid
  6357.         if @retcode <> 0 or @@error <> 0
  6358.             goto UNDO
  6359.  
  6360.        end
  6361.     else
  6362.     BEGIN
  6363.         /*
  6364.         ** Clear the filter id and filter_clause.
  6365.         */
  6366.         update sysarticles set filter = 0,
  6367.            filter_clause = NULL
  6368.            where pubid = @pubid
  6369.               and name = @article
  6370.         if @@error <> 0
  6371.             goto UNDO
  6372.  
  6373.         ---------------------------------------------------
  6374.         -- SQL SERVER 7.0 ONLY:  remove parent_id from filter proc
  6375.         ---------------------------------------------------
  6376.  
  6377.         select @obid = object_id( @qualified_table_name )
  6378.         if exists ( select * from sysobjects where name = @object
  6379.                 and type = 'RF')
  6380.         begin
  6381.             EXEC @retcode = dbo.sp_MSsetfilterparent @object, 0
  6382.             if @retcode <> 0 or @@error <> 0
  6383.                 goto UNDO
  6384.         end
  6385.         EXEC @retcode = dbo.sp_MSsetfilteredstatus @obid
  6386.         if @retcode <> 0 or @@error <> 0
  6387.             goto UNDO
  6388.     END
  6389.  
  6390.     -- Have to call this stored procedure to invalidate existing snapshot or reint
  6391.     -- subscriptions if needed
  6392.     EXECUTE @retcode  = dbo.sp_MSreinit_article
  6393.         @publication = @publication, 
  6394.         @article = @article,
  6395.         @need_new_snapshot = 1,
  6396.         @need_reinit_subscription = 1
  6397.         ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  6398.         ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  6399.     IF @@ERROR <> 0 OR @retcode <> 0
  6400.         GOTO UNDO
  6401.  
  6402.     /*
  6403.     ** Force the article cache to be refreshed with the new definition.
  6404.     */
  6405.     EXECUTE dbo.sp_replflush
  6406.     COMMIT TRANSACTION
  6407.     return 0
  6408. UNDO:
  6409.     if @@trancount > 0
  6410.     begin
  6411.         ROLLBACK TRANSACTION articlefilter
  6412.         commit tran
  6413.     end
  6414.     RETURN (1)
  6415. END
  6416. go
  6417.  
  6418. dump tran master with no_log
  6419. go
  6420.  
  6421. EXEC dbo.sp_MS_marksystemobject sp_articlefilter
  6422. GO
  6423.  
  6424. create procedure sp_MSscript_article_view 
  6425. @artid int,
  6426. @view_name sysname, 
  6427. @include_timestamps bit
  6428. as
  6429. declare @base_objid int
  6430. declare @columns varbinary(32)
  6431. declare @user_name sysname
  6432. declare @table_name sysname
  6433. declare @qualified_table_name nvarchar(520)
  6434. declare @filter_clause nvarchar(4000)
  6435.  
  6436. declare @cmdfrag nvarchar(4000)
  6437. declare @separator nvarchar(1)
  6438. declare @colname sysname
  6439.  
  6440. declare @retcode int
  6441.  
  6442. select @table_name = so.name,
  6443.        @base_objid = art.objid,
  6444.        @columns = art.columns,
  6445.        @user_name = USER_NAME(so.uid),
  6446.        @table_name = so.name,
  6447.        @qualified_table_name = QUOTENAME(USER_NAME(so.uid)) + '.' + QUOTENAME(so.name),
  6448.        @filter_clause = art.filter_clause
  6449.        from sysarticles art, sysobjects so
  6450.        where art.artid = @artid
  6451.        and art.objid = so.id
  6452.  
  6453. create table #tempcmd( c1 int identity NOT NULL, cmdfrag nvarchar(4000) collate database_default )
  6454.  
  6455. insert into #tempcmd (cmdfrag) values ( N'create view ' + QUOTENAME(@view_name) + N'as select ' )
  6456.  
  6457. create table #tmp (colid int NOT NULL primary key, name sysname collate database_default not null, published bit NOT NULL)
  6458.  
  6459. insert into #tmp select colid, name,
  6460.     convert(bit, convert( varbinary, substring( convert( nvarchar(16), @columns ), 16 - floor((colid-1)/16),1 )) & power( 2, ((colid-1)%16)))
  6461.     from syscolumns
  6462.     where id = @base_objid
  6463.  
  6464. if 1 = @include_timestamps
  6465. begin
  6466.     update #tmp set published = 1 where colid = (select colid from syscolumns c
  6467.         where c.id = @base_objid and c.xtype = 189)
  6468. end
  6469.  
  6470. declare hc  CURSOR LOCAL FAST_FORWARD FOR select name from #tmp
  6471.     where published = 1 order by colid asc
  6472. open hc
  6473. fetch hc into @colname
  6474.  
  6475. select @cmdfrag = N''
  6476. select @separator = N''
  6477.  
  6478. while (@@fetch_status <> -1)
  6479. begin
  6480.     if datalength( @cmdfrag ) > 3500 
  6481.     begin
  6482.         insert into #tempcmd(cmdfrag) values (@cmdfrag)
  6483.         select @cmdfrag = N''
  6484.     end
  6485.     select @cmdfrag = @cmdfrag + @separator + quotename(@colname)
  6486.  
  6487.     select @separator = N','
  6488.     fetch hc into @colname
  6489. end            
  6490. close hc
  6491. deallocate hc
  6492.  
  6493. insert into #tempcmd( cmdfrag ) values (@cmdfrag) 
  6494.  
  6495. insert into #tempcmd( cmdfrag ) values (N' from ')
  6496. insert into #tempcmd( cmdfrag ) values (@qualified_table_name)
  6497.  
  6498.  
  6499. insert into #tempcmd( cmdfrag ) values (N' where permissions(' + 
  6500.     convert(nvarchar(10), @base_objid)  + ') & 1 = 1 ')
  6501.  
  6502. if( @filter_clause is not null and datalength( @filter_clause ) > 0 )
  6503. begin
  6504.     exec @retcode = sp_MSsubst_filter_names @user_name, @table_name, @filter_clause output
  6505.     if @retcode <> 0 or @@error <> 0
  6506.         return 1        
  6507.     insert into #tempcmd( cmdfrag ) values ('and (' + @filter_clause + ')')
  6508. end
  6509.  
  6510. select cmdfrag from #tempcmd order by c1 asc
  6511.  
  6512. return 0
  6513. go
  6514.  
  6515. EXEC dbo.sp_MS_marksystemobject sp_MSscript_article_view 
  6516. GO
  6517.  
  6518.  
  6519. print ''
  6520. print 'Creating procedure sp_articleview'
  6521. go
  6522. create procedure sp_articleview (
  6523.     @publication sysname,        /* Publication name */
  6524.     @article sysname,          /* Article name */
  6525.     @view_name nvarchar (386) = NULL,  /* View name */
  6526.     @filter_clause ntext = NULL            /* Article's filter clause */
  6527.     ,@change_active int = 0
  6528.     ,@force_invalidate_snapshot bit = 0    /* Force invalidate existing snapshot */
  6529.     ,@force_reinit_subscription bit = 0    /* Force reinit subscription */
  6530. )
  6531. as
  6532. BEGIN
  6533.     declare @pubid smallint
  6534.             ,@table_name sysname
  6535.             ,@user_id int
  6536.             ,@user_name sysname
  6537.             ,@columns varbinary (32)
  6538.             ,@name sysname
  6539.             ,@retcode int
  6540.             ,@view_id int
  6541.             ,@type tinyint
  6542.             ,@table_id int
  6543.             ,@previous_view sysname
  6544.             ,@quoted_prev_view sysname
  6545.             ,@colid int
  6546.             ,@object sysname
  6547.             ,@quoted_object nvarchar(512)
  6548.             ,@artid int
  6549.             ,@active tinyint
  6550.             ,@allow_sync_tran bit
  6551.             ,@allow_queued_tran bit
  6552.             ,@filter_id int
  6553.  
  6554.     select @active = 2
  6555.  
  6556.     /*
  6557.     ** Security Check.
  6558.     */
  6559.     exec @retcode = dbo.sp_MSreplcheck_publish
  6560.     if @@ERROR <> 0 or @retcode <> 0
  6561.         return(1)
  6562.  
  6563.     /*
  6564.     ** Parameter Check:  @publication.
  6565.     ** Make sure that the publication exists and that it conforms to the
  6566.     ** rules for identifiers.
  6567.     */
  6568.     if @publication is null
  6569.            begin
  6570.               RAISERROR (14043, 16, -1, '@publication')
  6571.               return (1)
  6572.            END
  6573.  
  6574.     execute @retcode = dbo.sp_validname @publication
  6575.     if @retcode <> 0
  6576.             RETURN (1)
  6577.  
  6578.     select @pubid = pubid
  6579.         ,@allow_sync_tran = allow_sync_tran
  6580.         ,@allow_queued_tran = allow_queued_tran        
  6581.     from syspublications where name = @publication
  6582.     if @pubid is null
  6583.     begin
  6584.         RAISERROR (20026, 11, -1, @publication)
  6585.         return (1)
  6586.     end
  6587.  
  6588.     /*
  6589.     ** Parameter Check:  @article.
  6590.     ** Check to make sure that the article exists in the publication.
  6591.     */
  6592.  
  6593.     if @article is null
  6594.        begin
  6595.               RAISERROR (14043, 16, -1, '@article')
  6596.               return (1)
  6597.            end
  6598.     
  6599.     /*
  6600.         execute @retcode = dbo.sp_validname @article
  6601.         if @retcode <> 0
  6602.        return (1)
  6603.        */
  6604.  
  6605.     /*
  6606.     ** Get the article information.
  6607.     */
  6608.     declare @status tinyint
  6609.     declare @objid int
  6610.     select @artid = art.artid, @table_name = so.name,
  6611.        @user_id = uid, @user_name = USER_NAME(so.uid),
  6612.        @columns = art.columns, @type = art.type,
  6613.        @status = art.status,
  6614.        @objid = art.objid,
  6615.        @view_id = art.sync_objid, @table_id = art.objid
  6616.         ,@type = art.type
  6617.         ,@filter_id = art.filter
  6618.        from sysarticles art, sysobjects so
  6619.        where art.pubid = @pubid
  6620.        and art.name = @article
  6621.        and art.objid = so.id
  6622.  
  6623.     /*
  6624.     ** Fail if there is no article information.
  6625.     */
  6626.     if @artid is null
  6627.        begin
  6628.               RAISERROR (20027, 11, -1, @article)
  6629.               return (1)
  6630.        end
  6631.  
  6632.         /*
  6633.         ** Error out if this is a not a table based article
  6634.         */
  6635.         IF NOT EXISTS ( SELECT * FROM sysarticles WHERE artid = @artid
  6636.                           AND pubid = @pubid
  6637.                           AND (type & 1) = 1 )
  6638.             BEGIN
  6639.                 RAISERROR (14112, 11, -1 )
  6640.                 RETURN (1)
  6641.             END
  6642.    
  6643.     
  6644.     -- Special handling for timestamp column for queued publication.
  6645.     -- Although timestamp values are not needed, they have to be presented in bcp files. Otherwise
  6646.     -- bcp in will fail with data file format error.
  6647.  
  6648.     declare @include_timestamps bit
  6649.     select @include_timestamps = 0
  6650.     
  6651.     if @allow_queued_tran = 1 and @status & 32 <> 0
  6652.     begin
  6653.         select @include_timestamps = 1
  6654.     end
  6655.     
  6656.     /* Break out the specified view name and get the non-ownerqual'd name, then validate that. */
  6657.     select @object = PARSENAME( @view_name, 1 )
  6658.  
  6659.     if @object IS NULL
  6660.     begin
  6661.         -- generate view name
  6662.         declare @viewname varchar(255)
  6663.         declare @guid uniqueidentifier
  6664.         set @guid = CONVERT(varbinary(16), LEFT(NEWID(),8))
  6665.         exec @retcode = master.dbo.xp_varbintohexstr @guid, @viewname OUTPUT
  6666.         if @@ERROR <> 0 OR @retcode <> 0
  6667.             return (1)
  6668.         set @viewname = 'syncobj_' + @viewname
  6669.         set @object = @viewname
  6670.     end
  6671.  
  6672.  
  6673.     select @quoted_object = QUOTENAME(@object)
  6674.  
  6675.     execute @retcode = dbo.sp_validname @object
  6676.     if @retcode <> 0
  6677.         return (1)
  6678.  
  6679.     -- Check if there are snapshot or subscriptions and raiserror if needed.
  6680.     EXECUTE @retcode  = dbo.sp_MSreinit_article
  6681.         @publication = @publication, 
  6682.         @article = @article,
  6683.         @need_new_snapshot = 1,
  6684.         @need_reinit_subscription = 1
  6685.         ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  6686.         ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  6687.         ,@check_only = 1
  6688.     IF @@ERROR <> 0 OR @retcode <> 0
  6689.         return 1
  6690.  
  6691. CreateView:
  6692.     begin tran
  6693.     save TRANSACTION articleview
  6694.  
  6695.     /*
  6696.     ** If the article has a generated view (not manually created), then
  6697.     ** drop the current view before creating the new one.
  6698.     */
  6699.     if ((@type & 0x5) <> 0x5) and @view_id <> 0
  6700.             and @view_id <> @table_id
  6701.     begin
  6702.         select @previous_view = object_name (@view_id)
  6703.         if @previous_view is not null and
  6704.                 exists (select * from sysobjects where name = @previous_view
  6705.                 and type = 'V')
  6706.         begin
  6707.             select @quoted_prev_view = QUOTENAME(@previous_view)
  6708.             exec ('drop view ' + @quoted_prev_view)
  6709.             if @@error <> 0
  6710.                 goto UNDO
  6711.         end
  6712.     end
  6713.  
  6714.     /*
  6715.     ** Construct and execute the view creation command.
  6716.     */
  6717.     -- Drop the existing view.
  6718.     -- Note: upgrade needs this logic
  6719.     if datalength(@filter_clause) > 0 and
  6720.         exists (select * from sysobjects where id = object_id(@object)
  6721.     and type = 'V') 
  6722.     begin
  6723.         exec ('drop view ' + @quoted_object)
  6724.         if @@error <> 0
  6725.             goto UNDO
  6726.     end
  6727.  
  6728.     ---------------------------------------------
  6729.     --  Update article definition 
  6730.     --  Set @filter_clause value
  6731.     ---------------------------------------------
  6732.  
  6733.     if datalength(@filter_clause) > 0
  6734.     begin
  6735.        update sysarticles set filter_clause = @filter_clause
  6736.           where pubid = @pubid
  6737.           and name = @article
  6738.         if @@error <> 0
  6739.             goto UNDO
  6740.     end
  6741.     else
  6742.     begin
  6743.        update sysarticles set filter_clause = NULL
  6744.           where pubid = @pubid
  6745.           and name = @article
  6746.         if @@error <> 0
  6747.             goto UNDO
  6748.     end
  6749.  
  6750.  
  6751.     -----------------------------------------------------------
  6752.     -- create the view
  6753.     -----------------------------------------------------------
  6754.  
  6755.     declare @cmd nvarchar(2000)
  6756.     declare @dbname sysname
  6757.  
  6758.     select @cmd = N'exec sp_MSscript_article_view ' + cast(@artid as nvarchar(20)) 
  6759.                 + N',N' + quotename(@object,'''') +  
  6760.                 + N',' + cast(@include_timestamps as nvarchar(1))
  6761.     select @dbname = db_name()
  6762.     
  6763.     exec @retcode = master..xp_execresultset @cmd, @dbname
  6764.     if @@error <> 0 or @retcode <> 0
  6765.         goto UNDO
  6766.  
  6767.     -----------------------------------------------------------
  6768.     -- grant the permission of the view to public so that non
  6769.     -- db_owner can do validation.
  6770.     -----------------------------------------------------------
  6771.     select @cmd = 'grant select on ' + QUOTENAME(@object) + ' to public'
  6772.     exec (@cmd)
  6773.     if @@error <> 0
  6774.         goto UNDO
  6775.  
  6776.  
  6777.     -----------------------------------------------------------
  6778.     -- Update the article's sync_objid with the new view id
  6779.     -----------------------------------------------------------
  6780.  
  6781.     select @view_id = id from sysobjects where name = @object and type = 'V'
  6782.     if @view_id is null or @view_id = 0
  6783.     begin
  6784.         RAISERROR (15001, 11, -1, @object)
  6785.         goto UNDO
  6786.     end
  6787.     else
  6788.     begin
  6789.         if (@user_name in ('dbo','INFORMATION_SCHEMA'))
  6790.             EXEC dbo.sp_MS_marksystemobject @object
  6791.     end
  6792.  
  6793.     ---------------------------------------------
  6794.     --  Update article definition 
  6795.     --  Set new sync_objid 
  6796.     ---------------------------------------------
  6797.  
  6798.     update sysarticles set sync_objid = @view_id
  6799.       where pubid = @pubid
  6800.       and name = @article
  6801.     if @@error <> 0 
  6802.         goto UNDO
  6803.  
  6804.     -- sp_repldropcolumn used @change_active = 2 to prepare, don't invalidate or reinitialize
  6805.     if @change_active <> 2
  6806.     begin
  6807.         -- Have to call this stored procedure to invalidate existing snapshot or reint
  6808.         -- subscriptions if needed
  6809.         EXECUTE @retcode  = dbo.sp_MSreinit_article
  6810.             @publication = @publication, 
  6811.             @article = @article,
  6812.             @need_new_snapshot = 1,
  6813.             @need_reinit_subscription = 1
  6814.             ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  6815.             ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  6816.         IF @@ERROR <> 0 OR @retcode <> 0
  6817.             GOTO UNDO
  6818.     end
  6819.  
  6820.     /*
  6821.     ** Force the article cache to be refreshed with the new definition.
  6822.     */
  6823.     EXECUTE dbo.sp_replflush
  6824.     COMMIT TRANSACTION
  6825.  
  6826.     --
  6827.     -- Validate that the new view does not exclude the horizontal filter
  6828.     --
  6829.     if ((@allow_sync_tran = 1 or @allow_queued_tran = 1) and
  6830.         (datalength(@filter_clause) > 0))
  6831.     begin
  6832.         select @cmd = N'select top 0 * into #dummy from ' + 
  6833.             quotename(@user_name) + N'.' + quotename(object_name(@view_id)) +
  6834.             N' where ' + cast(@filter_clause as nvarchar(4000))
  6835.         exec (@cmd)
  6836.         if (@@error != 0)
  6837.         begin
  6838.             --
  6839.             -- The row filter does not work for the current view
  6840.             --
  6841.             declare @h_filter nvarchar(4000)
  6842.             select @h_filter = cast(@filter_clause as nvarchar(4000))
  6843.             raiserror(21392, 16, 1, @h_filter, @object, @article, @publication)
  6844.             
  6845.             --
  6846.             -- drop the filter if not manually generated 
  6847.             --
  6848.             if ((@type & 0x3) <> 0x3) and @filter_id <> 0
  6849.             begin
  6850.                 if exists (select * from sysobjects where id = @filter_id and type = 'RF')
  6851.                 begin
  6852.                     declare @filter_proc nvarchar(386)
  6853.                     exec dbo.sp_MSget_qualified_name @filter_id, @filter_proc output
  6854.                     exec ('drop procedure ' + @filter_proc)
  6855.  
  6856.                     update dbo.sysarticles set filter = 0, filter_clause = NULL
  6857.                         where pubid = @pubid and name = @article
  6858.  
  6859.                     raiserror(21393, 16, 1, @h_filter, @article, @publication)
  6860.                 end
  6861.             end
  6862.             return 1
  6863.         end
  6864.     end
  6865.  
  6866.     return 0
  6867. UNDO:
  6868.     if @@trancount > 0
  6869.     begin
  6870.         ROLLBACK TRANSACTION articleview
  6871.         commit tran
  6872.     end
  6873.     RETURN (1)
  6874. END
  6875. go
  6876.  
  6877. EXEC dbo.sp_MS_marksystemobject sp_articleview
  6878. GO
  6879.  
  6880. dump tran master with no_log
  6881. go
  6882.  
  6883. print ''
  6884. print 'Creating procedure sp_MSaddexearticle'
  6885. go
  6886. CREATE PROCEDURE sp_MSaddexecarticle
  6887.     @publication sysname,               /* publication name */
  6888.     @article     sysname,             /* article name */
  6889.     @source_proc nvarchar (92),                 /* table name */
  6890.     @destination_proc sysname = NULL,           /* destination table name */
  6891.     @type sysname = NULL,                       /* article type */
  6892.     @creation_script nvarchar (127) = NULL,           /* article schema script */
  6893.     @description nvarchar (255) = NULL,                 /* article description */
  6894.     @pre_creation_cmd nvarchar(10) = 'drop',           /* 'none', 'drop', 'delete', 'truncate' */
  6895.     @schema_option binary(8) = NULL,    /* script out stored procedure */
  6896.     @destination_owner sysname,
  6897.     @article_id int OUTPUT
  6898.  
  6899.     AS
  6900.  
  6901.  
  6902.     SET NOCOUNT ON
  6903.  
  6904.     /* variables for SP_NAMECRACK */
  6905.  
  6906.     DECLARE @site sysname
  6907.     DECLARE @db sysname
  6908.     DECLARE @owner sysname
  6909.     DECLARE @object sysname
  6910.  
  6911.     DECLARE @retcode   int
  6912.  
  6913.     DECLARE @procid    int
  6914.     DECLARE @procnum   smallint
  6915.     DECLARE @pubid     int
  6916.     DECLARE @precmdid  int
  6917.  
  6918.     DECLARE @typeid      smallint
  6919.     DECLARE @publish_bit smallint
  6920.     DECLARE @incompatible_typeid smallint
  6921.  
  6922.     DECLARE @cmd nvarchar(255)
  6923.     DECLARE @sysobj_colname  sysname
  6924.  
  6925.     SELECT  @typeid      = 24
  6926.  
  6927.  
  6928.     SELECT @sysobj_colname = 'replinfo'
  6929.     SELECT @publish_bit = 1
  6930.  
  6931.  
  6932.     /*
  6933.     ** Parameter Check: @article.
  6934.     ** The @article name cannot be NULL and must conform to the rules
  6935.     ** for identifiers.
  6936.     */
  6937.  
  6938.     IF @article IS NULL
  6939.         BEGIN
  6940.             RAISERROR (14043, 16, -1, '@article')
  6941.             RETURN (1)
  6942.         END
  6943.     
  6944.     /*
  6945.     EXECUTE @retcode = dbo.sp_validname @article
  6946.  
  6947.     IF @retcode <> 0
  6948.     return(1)
  6949.     */
  6950.  
  6951.     if LOWER(@article) = 'all'
  6952.         BEGIN
  6953.             RAISERROR (14032, 16, -1, '@article')
  6954.             RETURN (1)
  6955.         END
  6956.  
  6957.     /*
  6958.     ** Parameter Check: @publication.
  6959.     ** The @publication name cannot be NULL and must conform to the rules
  6960.     ** for identifiers.
  6961.     */
  6962.  
  6963.     IF @publication IS NULL
  6964.         BEGIN
  6965.             RAISERROR (14043, 16, -1, '@publication')
  6966.             RETURN (1)
  6967.         END
  6968.  
  6969.     EXECUTE @retcode = dbo.sp_validname @publication
  6970.  
  6971.     IF @retcode <> 0
  6972.     RETURN (1)
  6973.  
  6974.     /*
  6975.     ** Parameter Check: @source_proc.
  6976.     ** Check to see that the @source_proc is local, that it conforms
  6977.     ** to the rules for identifiers, and that it is a procedure
  6978.     */
  6979.  
  6980.     IF @source_proc IS NULL
  6981.     BEGIN
  6982.         RAISERROR (14043, 16, -1, '@source_proc')
  6983.         RETURN (1)
  6984.     END
  6985.  
  6986.    select @object = PARSENAME( @source_proc, 1 )
  6987.    select @owner  = PARSENAME( @source_proc, 2 )
  6988.    select @db     = PARSENAME( @source_proc, 3 )
  6989.    select @site   = PARSENAME( @source_proc, 4 )
  6990.  
  6991.    if @object IS NULL
  6992.          return 1
  6993.  
  6994.  
  6995.     IF @source_proc LIKE '%.%.%' AND @db <> DB_NAME()
  6996.     BEGIN
  6997.         RAISERROR (14004, 16, -1, @source_proc)
  6998.         RETURN (1)
  6999.     END
  7000.     
  7001.  
  7002.     /*
  7003.     **  Get the id of the @source_proc
  7004.     */
  7005.  
  7006.     SELECT @procid = id
  7007.       FROM sysobjects
  7008.      WHERE id = OBJECT_ID(@source_proc)
  7009.      AND   type = 'P'
  7010.  
  7011.     IF @procid IS NULL
  7012.     BEGIN
  7013.         RAISERROR (14027, 11, -1, @source_proc)
  7014.         RETURN (1)
  7015.     END
  7016.  
  7017.     /*
  7018.     ** Parameter Check:  @destination_proc.
  7019.     ** If the destination proc is not specified, assume it's the same
  7020.     ** as the source. 
  7021.     */
  7022.     
  7023.     IF @destination_proc IS NULL
  7024.     BEGIN
  7025.         -- Perform parsing only if the destination_proc parameter is not provided
  7026.         SELECT @destination_proc = @source_proc
  7027.  
  7028.         select @object = PARSENAME( @destination_proc, 1 )
  7029.         select @owner  = PARSENAME( @destination_proc, 2 )
  7030.         select @db     = PARSENAME( @destination_proc, 3 )
  7031.         select @site   = PARSENAME( @destination_proc, 4 )
  7032.  
  7033.         if @object IS NULL
  7034.              return 1 
  7035.     END
  7036.  
  7037.     /*
  7038.     ** Get the pubid.
  7039.     */
  7040.  
  7041.     SELECT @pubid = pubid FROM syspublications WHERE name = @publication
  7042.  
  7043.     IF @pubid IS NULL
  7044.         BEGIN
  7045.             RAISERROR (14027, 11, -1, @publication)
  7046.             RETURN (1)
  7047.         END
  7048.  
  7049.     /*
  7050.     ** Parameter Check:  @article, @publication.
  7051.     ** Check if the article already exists in this publication.
  7052.     */
  7053.  
  7054.     IF EXISTS (SELECT *
  7055.                  FROM sysextendedarticlesview
  7056.                 WHERE pubid = @pubid
  7057.                   AND name = @article)
  7058.         BEGIN
  7059.             RAISERROR (14030, 16, -1, @article, @publication)
  7060.             RETURN (1)
  7061.         END
  7062.  
  7063.  
  7064.     /*
  7065.     ** Set the precmdid.  The default type is 'drop'.
  7066.     **
  7067.     **      @precmdid   pre_creation_cmd
  7068.     **      =========   ================
  7069.     **            0     none
  7070.     **          1     drop
  7071.     */
  7072.     IF LOWER(@pre_creation_cmd collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('none', 'drop')
  7073.        BEGIN
  7074.           RAISERROR (14111, 16, -1)
  7075.           RETURN (1)
  7076.        END
  7077.  
  7078.     /*
  7079.     ** Determine the integer value for the pre_creation_cmd.
  7080.     */
  7081.  
  7082.     IF LOWER(@pre_creation_cmd collate SQL_Latin1_General_CP1_CS_AS) = 'none'
  7083.        SELECT @precmdid = 0
  7084.     ELSE IF LOWER(@pre_creation_cmd collate SQL_Latin1_General_CP1_CS_AS) = 'drop'
  7085.        SELECT @precmdid = 1
  7086.  
  7087.     /*  Determine 'type' value for article.
  7088.     **
  7089.     **            8     proc exec
  7090.     **           24     serializable proc exec
  7091.     */
  7092.  
  7093.     IF @type IS NULL
  7094.     BEGIN
  7095.         SELECT @type = 'serializable proc exec'
  7096.     END
  7097.     ELSE IF LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('proc exec', 'serializable proc exec')
  7098.     BEGIN
  7099.             RAISERROR (14118, 16, -1)
  7100.             RETURN (1)
  7101.     END
  7102.  
  7103.     IF LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) = 'proc exec'
  7104.     BEGIN
  7105.        SELECT @typeid = 8
  7106.        SELECT @incompatible_typeid = 24
  7107.     END
  7108.     ELSE IF LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) = 'serializable proc exec'
  7109.     BEGIN
  7110.        SELECT @typeid = 24
  7111.        SELECT @incompatible_typeid = 8
  7112.     END
  7113.  
  7114.     -- make sure we haven't already created an article of a different type
  7115.     -- on this proc
  7116.  
  7117.     IF EXISTS ( select * from sysobjects where id = @procid
  7118.                 and replinfo & @incompatible_typeid = @incompatible_typeid )
  7119.     BEGIN
  7120.        RAISERROR (21024, 16, -1, @source_proc )
  7121.        RETURN(1)
  7122.     END
  7123.  
  7124.     /*
  7125.     ** Parameter Check:  @creation_script and @schema_option
  7126.     ** @schema_option is null, set the default value
  7127.     */
  7128.     IF @schema_option IS NULL
  7129.     BEGIN
  7130.         SELECT @schema_option = 1
  7131.     /* 
  7132.         RAISERROR (14043, 16, -1, '@schema_option')
  7133.         RETURN (1)
  7134.         */
  7135.     END
  7136.  
  7137.     IF @schema_option <> 0x0000000000000000 AND 
  7138.        @schema_option <> 0x0000000000000001 AND
  7139.        @schema_option <> 0x0000000000002000 AND
  7140.        @schema_option <> 0x0000000000002001  
  7141.     BEGIN
  7142.         RAISERROR (20014, 10, -1)
  7143.         RETURN (1)
  7144.     END
  7145.  
  7146.     /*
  7147.     **  Add article to sysarticles and update sysobjects category bit.
  7148.     */
  7149.  
  7150.     begin tran
  7151.     save TRAN sp_MSaddexecarticle
  7152.         INSERT sysarticles (columns, creation_script, del_cmd, description,
  7153.                             dest_table, filter, filter_clause, ins_cmd, name,
  7154.                 objid, pre_creation_cmd, pubid,
  7155.                             status, sync_objid, type, upd_cmd, schema_option,
  7156.                             dest_owner)
  7157.         VALUES (0, @creation_script, NULL, @description,
  7158.                 @destination_proc, 0, '', NULL, @article,
  7159.                 @procid, @precmdid, @pubid,
  7160.                 0, @procid, @typeid, NULL, @schema_option,
  7161.                 @destination_owner)
  7162.  
  7163.         IF @@ERROR <> 0
  7164.         BEGIN
  7165.             if @@trancount > 0
  7166.             begin
  7167.                 ROLLBACK TRAN sp_MSaddexecarticle
  7168.                 commit tran
  7169.             end
  7170.             RETURN (1)
  7171.         END
  7172.  
  7173.         SELECT @article_id = @@IDENTITY
  7174.  
  7175.         select @cmd = 'UPDATE sysobjects SET ' + @sysobj_colname
  7176.         select @cmd = @cmd + ' = ' + @sysobj_colname + ' | ' + CONVERT( nvarchar, @publish_bit )
  7177.         select @cmd = @cmd + ' WHERE id = (SELECT objid FROM sysarticles WHERE name = '''
  7178.         select @cmd = @cmd + @article + ''' and pubid = ' + CONVERT( nvarchar, @pubid ) + ')'
  7179.  
  7180.         EXEC (@cmd)
  7181.  
  7182.         IF @@ERROR <> 0
  7183.         BEGIN
  7184.             if @@trancount > 0
  7185.             begin
  7186.                 ROLLBACK TRAN sp_MSaddexecarticle
  7187.                 commit tran
  7188.             end
  7189.             RETURN (1)
  7190.         END
  7191.  
  7192.  
  7193.     COMMIT TRAN
  7194. go
  7195.  
  7196. EXEC dbo.sp_MS_marksystemobject sp_MSaddexecarticle
  7197. GO
  7198.  
  7199. print ''
  7200. print 'Creating procedure sp_MSaddschemaarticle'
  7201. go
  7202.  
  7203. CREATE PROCEDURE sp_MSaddschemaarticle
  7204.     @publication        sysname,        /* Name of the publciation */
  7205.     @article            sysname,        /* Name of the article */
  7206.     @source_object      sysname,        /* Name of object to be replicated */
  7207.     @destination_object sysname,        /* Name of the object created on the subscriber */
  7208.     @type               tinyint,        /* Must be one of 0x20, 0x40, or 0x80 */
  7209.     @creation_script    nvarchar(255),  /* custom creation script for the article */
  7210.     @description        nvarchar(255),  /* article description */
  7211.     @pre_creation_cmd   nvarchar(10),   /* must be 'none' or 'drop' */
  7212.     @schema_option      binary(8),
  7213.     @destination_owner  sysname,        /* owner of the article object on the subscriber */
  7214.     @status             tinyint, 
  7215.     @artid              int OUTPUT
  7216. AS
  7217.     SET NOCOUNT ON
  7218.     DECLARE @retcode int
  7219.         
  7220.     DECLARE @source_owner           sysname
  7221.     DECLARE @object                 sysname
  7222.     DECLARE @bInTran                bit
  7223.     DECLARE @pubid                  int
  7224.     DECLARE @source_objid           int
  7225.     DECLARE @pre_creation_cmdid     tinyint
  7226.     
  7227.     /* Variables for setting up RPC call to the Distributor */
  7228.     DECLARE @distproc               nvarchar(2000)
  7229.     DECLARE @distributor            sysname
  7230.     DECLARE @distributiondb         sysname
  7231.     DECLARE @dbname                 sysname
  7232.     DECLARE @valid_schema_options   int
  7233.     
  7234.     SELECT @bInTran = 0
  7235.  
  7236.     SELECT @source_owner = PARSENAME(@source_object, 2)
  7237.     SELECT @object = PARSENAME(@source_object, 1)
  7238.  
  7239.     /* Note that @article & @publication has been by sp_addarticle 
  7240.        as non-null */
  7241.         
  7242.     /*
  7243.     ** Get the pubid of the publication
  7244.     */
  7245.     SELECT @pubid = NULL
  7246.     SELECT @pubid = pubid
  7247.       FROM syspublications
  7248.      WHERE name = @publication
  7249.  
  7250.     IF @pubid IS NULL
  7251.     BEGIN
  7252.         RAISERROR (14027, 11, -1, @publication)
  7253.         RETURN (1)
  7254.     END
  7255.  
  7256.     /*
  7257.     ** Get the source object id
  7258.     */
  7259.     SELECT @source_objid = NULL
  7260.     SELECT @source_objid = OBJECT_ID(@source_object)    
  7261.  
  7262.     /*
  7263.     **  Destination object name
  7264.     */
  7265.     IF @destination_object IS NULL
  7266.         SELECT @destination_object = @source_object
  7267.  
  7268.     /*
  7269.     ** Parameter check: @type
  7270.     ** @type must correspond to the object type of the source object
  7271.     **
  7272.     ** @type = 0x20 => source object type = 'P'
  7273.     ** @type = 0x40 => source object type = 'V'
  7274.     ** @type = 0x80 => source object type = 'FN' OR 'TF' OR 'IF'
  7275.     */
  7276.     IF @type = 0x20
  7277.     BEGIN
  7278.         IF NOT EXISTS (SELECT *
  7279.                          FROM sysobjects
  7280.                         WHERE id = @source_objid
  7281.                           AND xtype = 'P ')
  7282.         BEGIN
  7283.             RAISERROR(21219, 16, -1)
  7284.             RETURN (1)
  7285.         END
  7286.     END
  7287.     ELSE IF @type = 0x40
  7288.     BEGIN
  7289.         IF NOT EXISTS (SELECT *
  7290.                          FROM sysobjects 
  7291.                         WHERE id = @source_objid
  7292.                           AND xtype = 'V ')
  7293.         BEGIN
  7294.             RAISERROR(21221, 16, -1)
  7295.             RETURN (1)
  7296.         END
  7297.     END   
  7298.     ELSE IF @type = 0x80
  7299.     BEGIN
  7300.         IF NOT EXISTS (SELECT *
  7301.                          FROM sysobjects 
  7302.                         WHERE id = @source_objid
  7303.                           AND (xtype in ('FN','TF','IF')))
  7304.         BEGIN
  7305.             RAISERROR(21228, 16, -1)            
  7306.             RETURN (1)
  7307.         END
  7308.     END
  7309.  
  7310.  
  7311.     /*
  7312.     ** Parameter check: @schema_option
  7313.     ** @schema_option can only contain the bits 0x0000000000000001 and
  7314.     ** 0x0000000000002000
  7315.     ** for schema only articles except view. View articles can contain 
  7316.     ** the options 0x0000000000000010, 0x0000000000000020, and 
  7317.     ** 0x0000000000000100 in addition to the aforementioned options.
  7318.     */
  7319.     IF @type = 0x40
  7320.     BEGIN
  7321.  
  7322.         -- Since only the lower 32 bits of @schema_option are
  7323.         -- currently used, the following check is sufficient.
  7324.         -- Note that @schema_option should have been padded out by now
  7325.         DECLARE @schema_option_lodword int
  7326.         SELECT @valid_schema_options = 0x2151
  7327.         SELECT @schema_option_lodword = fn_replgetbinary8lodword(@schema_option)
  7328.         IF (@schema_option_lodword & ~@valid_schema_options) <> 0
  7329.         BEGIN
  7330.             RAISERROR (21229, 16, -1)
  7331.             RETURN (1)
  7332.         END
  7333.     END
  7334.     ELSE IF @schema_option NOT IN (0x0000000000000000,
  7335.                                    0x0000000000000001,
  7336.                                    0x0000000000002000,
  7337.                                    0x0000000000002001)
  7338.     BEGIN
  7339.         RAISERROR (21222, 16, -1)
  7340.         RETURN (1)
  7341.     END 
  7342.     
  7343.     /*
  7344.     ** Parameter check: @pre_creation_command must be
  7345.     ** 'drop' (id = 1) or 'none' (id = 0)
  7346.     */
  7347.     SELECT @pre_creation_cmd = LOWER(@pre_creation_cmd collate SQL_Latin1_General_CP1_CS_AS)
  7348.     IF @pre_creation_cmd NOT IN (N'none', N'drop')
  7349.     BEGIN
  7350.         RAISERROR(21223, 16, -1)
  7351.         RETURN (1)
  7352.     END
  7353.     
  7354.     IF @pre_creation_cmd = N'none'
  7355.         SELECT @pre_creation_cmdid = 0
  7356.     ELSE IF @pre_creation_cmd = N'drop'
  7357.         SELECT @pre_creation_cmdid = 1
  7358.     
  7359.     /*
  7360.     ** Parameter Check:  @article, @publication.
  7361.     ** Check if the article already exists in this publication.
  7362.     */
  7363.  
  7364.     IF EXISTS (SELECT *
  7365.                  FROM sysextendedarticlesview
  7366.                 WHERE pubid = @pubid
  7367.                   AND name = @article)
  7368.         BEGIN
  7369.             RAISERROR (14030, 16, -1, @article, @publication)
  7370.             RETURN (1)
  7371.         END
  7372.  
  7373.     BEGIN TRANSACTION sp_MSaddschemaarticle
  7374.     SAVE TRANSACTION sp_MSaddschemaarticle
  7375.     SELECT @bInTran = 1    
  7376.  
  7377.     -- Add a dummy record to sysarticles to reserve an artid
  7378.     INSERT sysarticles (dest_table, filter, name, objid, pubid, 
  7379.                         pre_creation_cmd, status, sync_objid, type)  
  7380.     VALUES (@destination_object, N'', @article, @source_objid, @pubid,
  7381.             @pre_creation_cmdid, @status, @source_objid, @type)
  7382.  
  7383.     IF @@ERROR <> 0
  7384.         GOTO Failure
  7385.  
  7386.     SELECT @artid = @@IDENTITY   
  7387.  
  7388.     -- Now that we have reserved an artid in sysarticles,
  7389.     -- we can remove the dummy record
  7390.     
  7391.     DELETE sysarticles WHERE artid = @artid AND pubid = @pubid
  7392.  
  7393.     IF @@ERROR <> 0
  7394.         GOTO Failure
  7395.  
  7396.     -- Insert a record into sysschemaarticles to represent this
  7397.     -- schema only article
  7398.     INSERT sysschemaarticles 
  7399.     VALUES (@artid, @creation_script, @description, @destination_object,
  7400.             @article, @source_objid, @pubid, @pre_creation_cmdid, @status,
  7401.             @type, @schema_option, @destination_owner)
  7402.  
  7403.     IF @@ERROR <> 0
  7404.         GOTO Failure
  7405.  
  7406.     -- Make a bit in replinfo to prevent the source object from
  7407.     -- being dropped
  7408.     UPDATE sysobjects SET replinfo = replinfo | 0x00000200 WHERE id = @source_objid
  7409.     
  7410.     IF @@ERROR <> 0
  7411.         GOTO Failure       
  7412.  
  7413.     COMMIT TRANSACTION  
  7414.  
  7415.     RETURN (0)
  7416. Failure:
  7417.  
  7418.     IF @bInTran = 1
  7419.     BEGIN
  7420.         ROLLBACK TRANSACTION sp_MSaddschemaarticle
  7421.         COMMIT TRANSACTION
  7422.     END
  7423.     RETURN (1)
  7424. go
  7425.  
  7426. EXEC dbo.sp_MS_marksystemobject sp_MSaddschemaarticle
  7427. GO
  7428.  
  7429. print ''
  7430. print 'Creating procedure sp_addarticle'
  7431. go
  7432. CREATE PROCEDURE sp_addarticle
  7433.     @publication        sysname,                /* publication name */
  7434.     @article            sysname,                /* article name */
  7435.     @source_table       nvarchar (386) = NULL,  /* table name */
  7436.     @destination_table  sysname = NULL,            /* destination table name */
  7437.     @vertical_partition nchar(5) = 'false',     /* vertical partition */
  7438.     @type               sysname = NULL,            /* article type */
  7439.     @filter                nvarchar (386) = NULL,  /* stored procedure used to filter table */
  7440.     @sync_object        nvarchar (386) = NULL,  /* view or table used for synchronization */
  7441.     @ins_cmd            nvarchar (255) = NULL,  /* insert format string */
  7442.     @del_cmd            nvarchar (255) = NULL,  /* delete format string */
  7443.     @upd_cmd            nvarchar (255) = NULL,  /* update format string */
  7444.     @creation_script    nvarchar (127) = NULL,  /* article schema script */
  7445.     @description        nvarchar (255) = NULL,  /* article description */
  7446.     @pre_creation_cmd   nvarchar(10) = 'drop',  /* 'none', 'drop', 'delete', 'truncate' */
  7447.     @filter_clause      ntext    = NULL,        /* where clause */
  7448.     @schema_option      varbinary(8) = NULL,
  7449.     @destination_owner  sysname = NULL,
  7450.     @status                tinyint = 16,           /* Default: binary command format */
  7451.     @source_owner       sysname = NULL,         /* NULL for 6.5 users, not NULL for 7.0 users */
  7452.     @sync_object_owner  sysname = NULL,         /* NULL for 6.5 users, not NULL for 7.0 users */
  7453.     @filter_owner       sysname = NULL,            /* NULL for 6.5 users, not NULL for 7.0 users */
  7454.     @source_object      sysname = NULL,            /* if @source_table is NULL, this parameter can not be NULL */
  7455.     @artid              int = NULL OUTPUT,       /* article id of the new article  */
  7456.     @auto_identity_range    nvarchar(5)    = 'FALSE',    /* set it to false for now - change is possible */
  7457.     @pub_identity_range        bigint    = NULL,
  7458.     @identity_range            bigint = NULL,
  7459.     @threshold                int    = NULL,
  7460.     @force_invalidate_snapshot bit = 0    /* Force invalidate existing snapshot */
  7461.     AS
  7462.  
  7463.     SET NOCOUNT ON
  7464.  
  7465.     /*
  7466.     ** Declarations.
  7467.     */    
  7468.     DECLARE @bak_source sysname
  7469.     DECLARE @num_columns int
  7470.     DECLARE @accessid smallint
  7471.     DECLARE @db sysname
  7472.     DECLARE @filterid int
  7473.     DECLARE @object sysname
  7474.     DECLARE @owner sysname
  7475.     DECLARE @pubid int
  7476.     DECLARE @publish_bit smallint
  7477.     DECLARE @retcode int
  7478.     DECLARE @site sysname
  7479.     DECLARE @syncid int
  7480.     DECLARE @tabid int
  7481.     DECLARE @typeid smallint
  7482.     DECLARE @pkkey sysname
  7483.     DECLARE @i int
  7484.     DECLARE @indid int
  7485.     DECLARE @precmdid int
  7486.     DECLARE @object_type nchar(2)
  7487.     DECLARE @push tinyint
  7488.     DECLARE @dbname sysname
  7489.     DECLARE @cmd nvarchar(255)
  7490.     DECLARE @fHasPk int
  7491.     DECLARE @no_sync tinyint
  7492.     DECLARE @immediate_sync bit
  7493.     DECLARE @is_filter_in_use int
  7494.     DECLARE @distributor sysname
  7495.     DECLARE @distribdb sysname
  7496.     DECLARE @distproc nvarchar (255)
  7497.     DECLARE @sync_method tinyint
  7498.     -- SyncTran
  7499.     DECLARE @autogen_sync_procs_id int
  7500.     DECLARE @custom_proc_name nvarchar(255)
  7501.     DECLARE @guid varbinary(16)
  7502.     declare @allow_sync_tran bit
  7503.     DECLARE @repl_freq int
  7504.     declare @allow_queued_tran bit
  7505.     declare @allow_dts bit
  7506.     declare @merge_pub_object_bit  int
  7507.     declare @valid_ins_cmd nvarchar(255)
  7508.             ,@valid_upd_cmd nvarchar(255)
  7509.             ,@valid_del_cmd nvarchar(255)
  7510.             ,@MSrepl_tran_version_datatype sysname
  7511.             ,@colid int
  7512.     declare @backward_comp_level int
  7513.     declare @schema_option_int int
  7514.     select @backward_comp_level = 10 -- default to sphinx
  7515.     
  7516.     select @merge_pub_object_bit     = 128
  7517.     SELECT @push = 0
  7518.     SELECT @dbname = DB_NAME()
  7519.  
  7520.     SELECT @publish_bit = 1
  7521.  
  7522.     SELECT @no_sync = 2 /* no sync type in syssubscriptions */
  7523.     /*
  7524.     ** Security Check.
  7525.     */
  7526.     exec @retcode = dbo.sp_MSreplcheck_publish
  7527.     if @@ERROR <> 0 or @retcode <> 0
  7528.         return(1)
  7529.  
  7530.     /*
  7531.     ** Padding out the specified schema option to the left
  7532.     */
  7533.     select @schema_option = fn_replprepadbinary8(@schema_option)
  7534.  
  7535.     /*
  7536.     ** Parameter Check: @article.
  7537.     ** The @article name cannot be NULL and must conform to the rules
  7538.     ** for identifiers.
  7539.     */
  7540.  
  7541.     IF @article IS NULL
  7542.         BEGIN
  7543.             RAISERROR (14043, 16, -1, '@article')
  7544.             RETURN (1)
  7545.         END
  7546.  
  7547.     exec @retcode = dbo.sp_MSreplcheck_name @article
  7548.     if @@ERROR <> 0 or @retcode <> 0
  7549.         return(1)
  7550.  
  7551.     if LOWER(@article) = 'all'
  7552.         BEGIN
  7553.             RAISERROR (14032, 16, -1, '@article')
  7554.             RETURN (1)
  7555.         END
  7556.  
  7557.     /*
  7558.     ** Parameter Check: @publication.
  7559.     ** The @publication name cannot be NULL and must conform to the rules
  7560.     ** for identifiers.
  7561.     */
  7562.  
  7563.     IF @publication IS NULL
  7564.     BEGIN
  7565.         RAISERROR (14043, 16, -1, '@publication')
  7566.         RETURN (1)
  7567.     END
  7568.  
  7569.     EXECUTE @retcode = dbo.sp_validname @publication
  7570.  
  7571.     IF @retcode <> 0
  7572.     RETURN (1)
  7573.  
  7574.     /*
  7575.     ** Parameter Check: @destination_owner.
  7576.     ** The @destination_owner must conform to the rules
  7577.     ** for identifiers.
  7578.     */
  7579.  
  7580.     if @destination_owner is not null
  7581.     BEGIN
  7582.         EXECUTE @retcode = dbo.sp_validname @destination_owner
  7583.  
  7584.         IF @retcode <> 0
  7585.             RETURN (1)
  7586.     END
  7587.  
  7588.     /*
  7589.     ** Parameter Check: @source_table.
  7590.     ** Check to see that the @source_table is local, that it conforms
  7591.     ** to the rules for identifiers, and that it is a table, and not
  7592.     ** a view or another database object.
  7593.     */
  7594.  
  7595.     IF @source_table IS NULL
  7596.         BEGIN
  7597.             if @source_object is NOT NULL
  7598.                 select @source_table = @source_object
  7599.             else
  7600.                 begin
  7601.                     RAISERROR (14043, 16, -1, '@source_table')
  7602.                     RETURN (1)
  7603.                 end
  7604.         END
  7605.  
  7606.     IF @source_owner is NULL -- 6.5 users only
  7607.     begin
  7608.         IF @source_table LIKE '%.%.%' AND PARSENAME(@source_table, 3) <> DB_NAME()
  7609.                BEGIN
  7610.                   RAISERROR (14004, 16, -1, @source_table)
  7611.                   RETURN (1)
  7612.                END
  7613.     end
  7614.  
  7615.     -- For 7.0 users, @source_owner is not nullable.
  7616.     
  7617.     select @bak_source = @source_table
  7618.     
  7619.     IF @source_owner is not NULL
  7620.         begin
  7621.             select @source_table = QUOTENAME(@source_owner) + '.' + QUOTENAME(@source_table)
  7622.             IF @destination_table IS NULL
  7623.                 SELECT @destination_table = @bak_source
  7624.         end
  7625.     ELSE 
  7626.     begin
  7627.         -- Make @source_table qualifed.
  7628.         select @tabid = object_id(@source_table)
  7629.         if @tabid is not null
  7630.         begin
  7631.             exec @retcode = dbo.sp_MSget_qualified_name @tabid, @source_table output
  7632.             if @retcode <> 0 or @@error <> 0
  7633.                 return 1    
  7634.             IF @destination_table IS NULL
  7635.             -- Set destination_table if not provided or default by now.
  7636.             -- If @source_table is qualified (6.x behavior) only use table name for destination name.
  7637.                 SELECT @destination_table = PARSENAME(@source_table, 1)    
  7638.         end
  7639.     end
  7640.         
  7641.     select @num_columns=count(*) from syscolumns where id = object_id(@source_table)
  7642.     if @num_columns > 255
  7643.         begin
  7644.             RAISERROR (20068, 16, -1, @source_table, 255)
  7645.             RETURN (1)
  7646.         end
  7647.  
  7648.     /*
  7649.     **  Get the id of the @source_table
  7650.     */
  7651.     SELECT @tabid = id, @object_type = type
  7652.     FROM sysobjects
  7653.     WHERE id = OBJECT_ID(@source_table)
  7654.  
  7655.     IF @tabid IS NULL
  7656.         BEGIN
  7657.             RAISERROR (14027, 11, -1, @source_table)
  7658.             RETURN (1)
  7659.         END
  7660.  
  7661.     /*
  7662.     ** Parameter Check: @type
  7663.     ** If the article is added as a 'schema-bound view schema only' article,
  7664.     ** make sure that the source object is a schema-bound view.
  7665.     ** Conversely, a schema-bound view cannot be published as a 
  7666.     ** 'view schema only' article.
  7667.     */
  7668.     IF @type IS NULL
  7669.         SELECT @type = 'logbased'
  7670.  
  7671.     select @type = lower(@type collate SQL_Latin1_General_CP1_CS_AS)
  7672.  
  7673.     if @type = N'indexed view schema only' and objectproperty(@tabid, 'IsSchemaBound') <> 1
  7674.     begin
  7675.         raiserror (21277, 11, -1, @source_table)        
  7676.         return (1)    
  7677.     end
  7678.  
  7679.     /*
  7680.     ** If the article is published as an IV logbased article, we'd better make
  7681.     ** sure that the view is schema bound and it has a clustered index.
  7682.     ** Conversely, a schema-bound view should never be published as a regular
  7683.     ** table logbased article.
  7684.     */
  7685.     if @type in (N'indexed view logbased', 
  7686.                  N'indexed view logbased manualfilter', 
  7687.                  N'indexed view logbased manualview', 
  7688.                  N'indexed view logbased manualboth') and 
  7689.         (isnull(objectproperty(@tabid, 'IsSchemaBound'),0) <> 1 or
  7690.          not exists (select * from sysindexes where id = @tabid) or
  7691.          isnull(objectproperty(@tabid, 'IsView'),0) = 0) 
  7692.     begin
  7693.         raiserror (21278, 11, -1, @source_table)
  7694.         return (1)
  7695.     end    
  7696.     
  7697.     if @type in (N'view schema only', 
  7698.                  N'logbased', 
  7699.                  N'logbased manualfilter', 
  7700.                  N'logbased manualview', 
  7701.                  N'logbased manualboth') and 
  7702.         objectproperty(@tabid, 'IsSchemaBound') = 1
  7703.     begin
  7704.         raiserror (21275, 11, -1, @source_table)
  7705.         return (1)
  7706.     end
  7707.  
  7708.     -- Check if there are snapshot or subscriptions and raiserror if needed.
  7709.     EXECUTE @retcode  = dbo.sp_MSreinit_article
  7710.         @publication = @publication, 
  7711.         -- Virtual subscriptions of all the articles will be deactivated.
  7712.         -- @article = @article,
  7713.         @need_new_snapshot = 1,
  7714.         @force_invalidate_snapshot = @force_invalidate_snapshot,
  7715.         @check_only = 1
  7716.     IF @@ERROR <> 0 OR @retcode <> 0
  7717.         return 1
  7718.  
  7719.  
  7720.     -- Encrypted objects are not publishable for replication
  7721.     IF @type IN (N'proc exec',
  7722.                  N'serializable proc exec',
  7723.                  N'proc schema only',
  7724.                  N'indexed view schema only',
  7725.                  N'indexed view logbased',
  7726.                  N'indexed view logbased manualfilter',
  7727.                  N'indexed view logbased manualview',
  7728.                  N'indexed view logbased manualboth',
  7729.                  N'view schema only',
  7730.                  N'func schema only')
  7731.     BEGIN
  7732.         IF EXISTS (SELECT * FROM syscomments
  7733.                     WHERE id = @tabid
  7734.                       AND encrypted = 1)
  7735.         BEGIN
  7736.             RAISERROR(21004, 16, -1, @source_table)        
  7737.             RETURN (1)
  7738.         END
  7739.     END   
  7740.  
  7741.     -- at this point, we've done all the common parameter checks.
  7742.     -- If this is a procedure execution article, branch to the proc execution publishing
  7743.     -- routine; or if this is a schema only procedure or view article, brach to the
  7744.     -- schema only article publishing routine; otherwise continue processing as if it were a table
  7745.  
  7746.     IF (@object_type = 'P' AND @type <> N'proc schema only') or 
  7747.         @type IN (N'proc schema only', N'view schema only', N'func schema only', 'indexed view schema only')
  7748.     BEGIN
  7749.         begin tran
  7750.         save TRAN sp_addarticle
  7751.  
  7752.         IF (@object_type = 'P' AND @type <> N'proc schema only')
  7753.         begin
  7754.  
  7755.             IF @schema_option IS NULL
  7756.             BEGIN
  7757.                 SELECT @schema_option = 0x0000000000000001
  7758.             END
  7759.  
  7760.             EXECUTE @retcode = dbo.sp_MSaddexecarticle @publication,
  7761.                 @article,
  7762.                 @source_table,
  7763.                 @destination_table,
  7764.                 @type,
  7765.                 @creation_script,
  7766.                 @description,
  7767.                 @pre_creation_cmd,
  7768.                 @schema_option,
  7769.                 @destination_owner,
  7770.                 @artid OUTPUT
  7771.         end
  7772.         else 
  7773.         begin
  7774.             -- Note: a transaction is started inside sp_MSaddschemaarticle        
  7775.             IF @schema_option IS NULL
  7776.             BEGIN
  7777.                 SELECT @schema_option = 0x0000000000000001
  7778.             END
  7779.  
  7780.             IF @type = N'proc schema only'
  7781.             BEGIN
  7782.                 SELECT @typeid = 0x20
  7783.             END
  7784.             ELSE IF @type = N'view schema only'
  7785.             BEGIN
  7786.                 SELECT @typeid = 0x40
  7787.             END    
  7788.             ELSE IF @type = N'func schema only'
  7789.             BEGIN
  7790.                 SELECT @typeid = 0x80
  7791.             select @backward_comp_level = 40 -- UDF not available in sphinx
  7792.             END
  7793.             ELSE IF @type = N'indexed view schema only'
  7794.             BEGIN
  7795.                 SELECT @typeid = 0x40
  7796.             select @backward_comp_level = 40 -- SchemaBinding not available in sphinx
  7797.             END    
  7798.  
  7799.             EXECUTE @retcode = dbo.sp_MSaddschemaarticle 
  7800.                 @publication = @publication,
  7801.                 @article = @article,
  7802.                 @source_object = @source_table,
  7803.                 @destination_object = @destination_table,
  7804.                 @type = @typeid,
  7805.                 @creation_script = @creation_script,
  7806.                 @description = @description,
  7807.                 @pre_creation_cmd = @pre_creation_cmd,
  7808.                 @schema_option = @schema_option,
  7809.                 @destination_owner = @destination_owner,
  7810.                 @status = @status,
  7811.                 @artid = @artid OUTPUT
  7812.  
  7813.         end
  7814.         IF @retcode <> 0 or @@error <> 0
  7815.             goto UNDO
  7816.     end
  7817.     ELSE
  7818.     begin
  7819.  
  7820.         /*
  7821.         ** Make sure that the table name specified is a table and not a view.
  7822.         */
  7823.  
  7824.         IF NOT EXISTS (SELECT * FROM sysobjects
  7825.             WHERE id = (SELECT OBJECT_ID(@source_table))
  7826.             AND type = 'U')
  7827.             AND NOT EXISTS ( SELECT * FROM sysobjects so, sysindexes si
  7828.             WHERE so.id = OBJECT_ID(@source_table)
  7829.             AND so.type = 'V'
  7830.             AND si.id = so.id )
  7831.         BEGIN
  7832.             RAISERROR (14028, 16, -1)
  7833.             RETURN (1)
  7834.         END
  7835.  
  7836.  
  7837.         /*
  7838.         ** Parameter Check:  @destination_table.
  7839.         ** If the destination table is not specified, assume it's the same
  7840.         ** as the source table.  Make sure that the table name is not qualified.
  7841.         */
  7842.  
  7843.         /*
  7844.         ** Parameter Check: @vertical_partition
  7845.         ** Check to make sure that the vertical partition is either TRUE or FALSE.
  7846.         */
  7847.  
  7848.         SELECT @vertical_partition = LOWER(@vertical_partition collate SQL_Latin1_General_CP1_CS_AS)
  7849.         IF @vertical_partition NOT IN ('true', 'false')
  7850.         BEGIN
  7851.             RAISERROR (14029, 16, -1)
  7852.             RETURN (1)
  7853.         END
  7854.  
  7855.         /*
  7856.         ** Parameter Check: @filter
  7857.         ** Make sure that the filter is a valid stored procedure.
  7858.         */
  7859.         IF @filter IS NOT NULL
  7860.         BEGIN
  7861.             IF @filter_owner IS NULL
  7862.             BEGIN
  7863.                 select @object = PARSENAME( @filter, 1 )
  7864.                 select @owner  = PARSENAME( @filter, 2 )
  7865.                 select @db     = PARSENAME( @filter, 3 )
  7866.                 select @site   = PARSENAME( @filter, 4 )
  7867.  
  7868.                 if @object IS NULL
  7869.                   return 1
  7870.             END  
  7871.             ELSE
  7872.             BEGIN
  7873.                 select @filter = QUOTENAME(@filter_owner) + '.' + QUOTENAME(@filter)
  7874.             END
  7875.  
  7876.             /*
  7877.             ** Get the id of the @filter
  7878.             */
  7879.             select @filterid = id from sysobjects where
  7880.                 id = OBJECT_ID(@filter) and type = 'RF'
  7881.             IF @filterid IS NULL
  7882.             BEGIN
  7883.                 RAISERROR (14027, 11, -1, @filter)
  7884.                 RETURN (1)
  7885.             END
  7886.  
  7887.             EXEC @is_filter_in_use = dbo.sp_MSdoesfilterhaveparent @filterid
  7888.             if( @is_filter_in_use <> 0 )
  7889.             BEGIN
  7890.                 RAISERROR( 21009, 11, -1 )
  7891.                 RETURN (1)
  7892.             END
  7893.         END
  7894.         ELSE
  7895.             select @filterid = 0
  7896.  
  7897.  
  7898.         /*
  7899.         ** Get the pubid and its properties
  7900.         */
  7901.         SELECT @pubid = pubid, @autogen_sync_procs_id = autogen_sync_procs, @sync_method = sync_method,
  7902.             @allow_sync_tran = allow_sync_tran,
  7903.             @allow_queued_tran = allow_queued_tran,
  7904.             @allow_dts    = allow_dts,
  7905.             @repl_freq = repl_freq 
  7906.         FROM syspublications where name = @publication
  7907.  
  7908.         IF @pubid IS NULL
  7909.             BEGIN
  7910.                 RAISERROR (14027, 11, -1, @publication)
  7911.                 RETURN (1)
  7912.             END
  7913.  
  7914.         -- Only allow table and index view for dts publications
  7915.         if @allow_dts <> 0 and @type not in ( 
  7916.             N'logbased', 
  7917.             N'logbased manualfilter', 
  7918.             N'logbased manualview', 
  7919.             N'logbased manualboth',
  7920.             N'indexed view logbased', 
  7921.             N'indexed view logbased manualfilter', 
  7922.             N'indexed view logbased manualview', 
  7923.             N'indexed view logbased manualboth')
  7924.         begin
  7925.             raiserror(20611, 16, -1)
  7926.             return(1)
  7927.         end
  7928.  
  7929.         -- can't do fancy type stuff with MVs!
  7930.  
  7931.         ELSE IF (@allow_sync_tran <> 0 
  7932.                 OR @allow_queued_tran <> 0)
  7933.                 AND EXISTS ( select * from sysobjects 
  7934.                     where id = OBJECT_ID(@source_table)
  7935.                     and xtype = 'V' )
  7936.         BEGIN
  7937.             RAISERROR(14059, 16, -1)
  7938.             RETURN 1
  7939.         END
  7940.         
  7941.         --
  7942.         -- parameter check: @status
  7943.         -- bits 8, 16, 64 can be set directly
  7944.         -- Other bits from 1 ~ 64 are used but cannot be set here.
  7945.         -- Bit 64 can only be set for publication that allows DTS.
  7946.         -- Bit 32 is set internally according to whether or not timestamp is in
  7947.         -- the partition for queued publications.
  7948.  
  7949.         IF (@status & ~ 88 ) <> 0 
  7950.         BEGIN
  7951.             RAISERROR( 21061, 16, -1, @status, @article )
  7952.             RETURN (1)
  7953.         END
  7954.         else if (@status & 64 <> 0 and @allow_dts = 0)
  7955.         begin
  7956.             raiserror(20590, 16, -1)
  7957.             return (1)
  7958.         end
  7959.  
  7960.  
  7961.         /*
  7962.         ** Parameter Check:  @article, @publication.
  7963.         ** Check if the article already exists in this publication.
  7964.         */
  7965.  
  7966.         IF EXISTS (SELECT *
  7967.                      FROM sysextendedarticlesview
  7968.                     WHERE pubid = @pubid
  7969.                       AND name = @article)
  7970.             BEGIN
  7971.                 RAISERROR (14030, 16, -1, @article, @publication)
  7972.                 RETURN (1)
  7973.             END
  7974.  
  7975.         /*
  7976.         ** Set the typeid.  The default type is logbased.  Anything else is
  7977.         ** currently undefined (reserved for future use).
  7978.         **
  7979.         **      @typeid     type
  7980.         **      =======     ========
  7981.         **          1     logbased
  7982.         **          3     logbased manualfilter
  7983.         **          5     logbased manualview
  7984.         **          7     logbased manualboth
  7985.         **          8     proc exec              (valid in dbo.sp_MSaddexecarticle)
  7986.         **          24    serializable proc exec (valid in dbo.sp_MSaddexecarticle)
  7987.         **          32    proc schema only       (valid in dbo.sp_MSaddschemaarticle)
  7988.         **          64    view schema only       (valid in dbo.sp_MSaddschemaarticle)
  7989.         **         128    func schema only       (valid in dbo.sp_MSaddschemaarticle)
  7990.         **       Note that for the following article types, the 256 bit is not really persisted
  7991.         **         257    indexed view logbased
  7992.         **         259    indexed view logbased manualfilter
  7993.         **         261    indexed view logbased manualview
  7994.         **         263    indexed view logbased manualboth
  7995.         **         320    indexed view schema only (valid in dbo.sp_MSaddschemaarticle)
  7996.         */
  7997.  
  7998.  
  7999.         IF LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) NOT IN 
  8000.                                     ('logbased', 
  8001.                                      'logbased manualfilter', 
  8002.                                      'logbased manualview', 
  8003.                                      'logbased manualboth',
  8004.                                      'indexed view logbased', 
  8005.                                      'indexed view logbased manualfilter', 
  8006.                                      'indexed view logbased manualview', 
  8007.                                      'indexed view logbased manualboth',
  8008.                                      'proc schema only', 
  8009.                                      'view schema only')
  8010.         BEGIN
  8011.             RAISERROR (14023, 16, -1)
  8012.             RETURN (1)
  8013.         END
  8014.  
  8015.         IF LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) = 'logbased' OR LOWER(@type) = 'indexed view logbased'
  8016.             SELECT @typeid = 1
  8017.         ELSE IF LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) = 'logbased manualfilter' OR LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) = 'indexed view logbased manualfilter'
  8018.            SELECT @typeid = 3
  8019.         ELSE IF LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) = 'logbased manualview' OR LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) = 'indexed view logbased manualview'
  8020.            SELECT @typeid = 5
  8021.         ELSE IF LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) = 'logbased manualboth' OR LOWER(@type collate SQL_Latin1_General_CP1_CS_AS) = 'indexed view logbased manualboth'
  8022.             SELECT @typeid = 7
  8023.  
  8024.         /*
  8025.         ** Set the precmdid.  The default type is 'drop'.
  8026.         **
  8027.         **      @precmdid   pre_creation_cmd
  8028.         **      =========   ================
  8029.         **            0     none
  8030.         **          1     drop
  8031.         **          2     delete
  8032.         **          3     truncate
  8033.         */
  8034.         IF LOWER(@pre_creation_cmd collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('none', 'drop', 'delete', 'truncate')
  8035.         BEGIN
  8036.             RAISERROR (14061, 16, -1)
  8037.             RETURN (1)
  8038.         END
  8039.  
  8040.         /*
  8041.         ** Determine the integer value for the pre_creation_cmd.
  8042.         */
  8043.         IF LOWER(@pre_creation_cmd collate SQL_Latin1_General_CP1_CS_AS) = 'none'
  8044.             SELECT @precmdid = 0
  8045.         ELSE IF LOWER(@pre_creation_cmd collate SQL_Latin1_General_CP1_CS_AS) = 'drop'
  8046.             SELECT @precmdid = 1
  8047.         ELSE IF LOWER(@pre_creation_cmd collate SQL_Latin1_General_CP1_CS_AS) = 'delete'
  8048.             SELECT @precmdid = 2
  8049.         ELSE IF LOWER(@pre_creation_cmd collate SQL_Latin1_General_CP1_CS_AS) = 'truncate'
  8050.             SELECT @precmdid = 3
  8051.  
  8052.         IF @sync_object IS NULL
  8053.             select @syncid = @tabid
  8054.         ELSE
  8055.         BEGIN
  8056.  
  8057.         IF @sync_object_owner is NULL  -- 6.5 only
  8058.         BEGIN
  8059.  
  8060.             /*
  8061.             ** Parameter Check: @sync_object.
  8062.             ** Check to see that the sync_object is local and that it
  8063.             ** conforms to the rules for identifiers.
  8064.             */
  8065.  
  8066.             select @object = PARSENAME( @sync_object, 1 )
  8067.             select @owner  = PARSENAME(  @sync_object, 2 )
  8068.             select @db     = PARSENAME(  @sync_object, 3 )
  8069.             select @site   = PARSENAME(  @sync_object, 4 )
  8070.  
  8071.             if @object IS NULL
  8072.                   return 1
  8073.  
  8074.  
  8075.             IF @sync_object LIKE '%.%.%' AND @db <> DB_NAME()
  8076.             BEGIN
  8077.                 RAISERROR (14004, 16, -1, @sync_object)
  8078.                 RETURN (1)
  8079.             END
  8080.  
  8081.         END -- end of 65 processing
  8082.         else -- for sphinx, @sync_object_owner can not be null
  8083.             select @sync_object = QUOTENAME(@sync_object_owner) + '.' + QUOTENAME(@sync_object)
  8084.             
  8085.             /*
  8086.             **  Get the id of the @sync_object
  8087.             */
  8088.  
  8089.             SELECT @syncid = id FROM sysobjects WHERE id = OBJECT_ID(@sync_object)
  8090.  
  8091.             IF @syncid IS NULL
  8092.             BEGIN
  8093.                 RAISERROR (14027, 11, -1, @sync_object)
  8094.                 RETURN (1)
  8095.             END
  8096.  
  8097.             /*
  8098.             ** Make sure the sync object specified is a table or a view.
  8099.             */
  8100.  
  8101.             IF NOT EXISTS (SELECT * FROM sysobjects
  8102.                     WHERE id = (SELECT OBJECT_ID(@sync_object))
  8103.                     AND (type = 'U' or
  8104.                          type = 'V'))
  8105.             BEGIN
  8106.                 RAISERROR (14031, 16, -1)
  8107.                 RETURN (1)
  8108.             END
  8109.         END
  8110.  
  8111.         /*
  8112.         ** If the publication is log-based, or allows updating subscribers
  8113.         ** make sure there is a primary key on the source table.
  8114.         ** or a UCI on the view.
  8115.         ** NOTE!  sprok in SPSUP.SQL
  8116.         */
  8117.         IF EXISTS (SELECT * FROM syspublications 
  8118.             WHERE pubid = @pubid AND
  8119.                 (repl_freq = 0 OR allow_sync_tran = 1 OR @allow_queued_tran = 1))
  8120.         BEGIN
  8121.             EXEC @fHasPk = dbo.sp_MSreplsup_table_has_pk @tabid
  8122.  
  8123.             IF @fHasPk = 0
  8124.             BEGIN
  8125.                 IF EXISTS ( select * from sysobjects 
  8126.                     where id = OBJECT_ID(@source_table)
  8127.                     and xtype = 'U' )
  8128.                 BEGIN
  8129.                     RAISERROR (14088, 16, -1, @source_table)
  8130.                 END
  8131.                 ELSE
  8132.                 BEGIN
  8133.                     RAISERROR( 14089, 16, -1, @source_table)
  8134.                 END
  8135.                 RETURN (1)
  8136.             END
  8137.         END
  8138.  
  8139.         /*
  8140.         ** Parameter Check:  @creation_script and @schema_option
  8141.         ** @schema_option cannot be null
  8142.         ** If @schema_option is 0, there have to be @creation_script defined.
  8143.         */
  8144.         IF @schema_option IS NULL
  8145.         BEGIN
  8146.             -- Snapshot publication, no custom proc. generation
  8147.             -- We need insert proc for snapshot publications for DTS.
  8148.             -- Do not generate user triggers by default (0x00100 - user trigger flag)
  8149.             IF @repl_freq = 1 and @allow_dts = 0
  8150.             BEGIN
  8151.                 SELECT @schema_option  = 0x0000000000000071
  8152.             END
  8153.             ELSE
  8154.             BEGIN
  8155.                 SELECT @schema_option  = 0x00000000000000F3
  8156.             END
  8157.  
  8158.             if (@allow_queued_tran = 1)
  8159.                 select @schema_option = fn_replprepadbinary8(fn_replgetbinary8lodword(@schema_option) | 0x8000)
  8160.         END
  8161.  
  8162.         /*
  8163.         ** Parameter Check: @schema_option
  8164.         ** If bit 0x2 is set, this cannot be an article for a snapshot publication
  8165.         ** For queued updating, DRI_Primary Key option has to be set
  8166.         */
  8167.         IF ((CONVERT(INT, @schema_option) & 0x2) <> 0) AND (@repl_freq = 1)
  8168.         BEGIN
  8169.             RAISERROR (21143, 16, -1)
  8170.             RETURN (1)
  8171.         END
  8172.         else if ((@allow_queued_tran = 1) and 
  8173.             ((fn_replgetbinary8lodword(@schema_option) & 0x8000) = 0))
  8174.         BEGIN
  8175.             RAISERROR (21394, 16, 1)
  8176.             RETURN (1)
  8177.         END
  8178.         
  8179.         /* 
  8180.         ** Since custom proc name is based on destination table name
  8181.         */
  8182.         
  8183.         if @allow_dts = 0
  8184.             set @custom_proc_name = @destination_table
  8185.         else
  8186.             set @custom_proc_name = @article
  8187.  
  8188.         -- Publication allow dts/queued must use parameterized commands and 
  8189.         -- ins/upd/del commands are generated 
  8190.         -- internally and are fixed (they will used as keys to find the correct transformations)
  8191.         if (@allow_dts = 1 or @allow_queued_tran = 1)
  8192.         begin
  8193.             select @valid_ins_cmd = N'CALL sp_MSins_' + @custom_proc_name
  8194.             IF @repl_freq = 0
  8195.             begin
  8196.                 --
  8197.                 -- Note :
  8198.                 -- Now that we are autogenrating the custom procs for queued
  8199.                 -- we will follow the current behavior :
  8200.                 -- for queued INS/UPD/DEL will use CALL/XCALL/XCALL respectively
  8201.                 -- for DTS INS/UPD/DEL will use CALL/XCALL/XCALL
  8202.                 -- In case it allows both queued and DTS, DTS will take precedence
  8203.                 -- YWU: Check this
  8204.                 --
  8205.                 select @valid_del_cmd = N'XCALL sp_MSdel_' + @custom_proc_name
  8206.                 if (@allow_queued_tran = 1)
  8207.                 begin
  8208.                     select @valid_upd_cmd = N'XCALL sp_MSupd_' + @custom_proc_name
  8209.                 end
  8210.                 if (@allow_dts = 1)
  8211.                 begin
  8212.                     if @status = 16
  8213.                         select @valid_upd_cmd = N'CALL sp_MSupd_' + @custom_proc_name
  8214.                     else 
  8215.                         select @valid_upd_cmd = N'XCALL sp_MSXpd_' + @custom_proc_name
  8216.                 end
  8217.             end
  8218.             else
  8219.             begin
  8220.                 select @valid_upd_cmd = N'SQL'
  8221.                 select @valid_del_cmd = N'SQL'
  8222.             end
  8223.  
  8224.             if (@allow_dts = 1)
  8225.             begin
  8226.                 -- For publication allows DTS, @status can only be 16 or 48
  8227.                 -- 
  8228.                 if  (@status <> 16 and @status <> 80) or
  8229.                     (@ins_cmd is not null and @ins_cmd <> @valid_ins_cmd) or 
  8230.                     (@upd_cmd is not null and @upd_cmd <> @valid_upd_cmd) or 
  8231.                     (@del_cmd is not null and @del_cmd <> @valid_del_cmd)
  8232.                 begin
  8233.                     raiserror(21174, 16, -1)
  8234.                     return (1)
  8235.                 end
  8236.             end 
  8237.             else if (@allow_queued_tran = 1)
  8238.             begin
  8239.                 if  (@ins_cmd is not null and @ins_cmd != @valid_ins_cmd) or 
  8240.                     (@upd_cmd is not null and @upd_cmd != @valid_upd_cmd) or 
  8241.                     (@del_cmd is not null and @del_cmd != @valid_del_cmd)
  8242.                 begin
  8243.                     raiserror(21191, 16, -1, @valid_ins_cmd, @valid_upd_cmd, @valid_del_cmd)
  8244.                     return (1)
  8245.                 end
  8246.             end
  8247.                 
  8248.             select @ins_cmd = @valid_ins_cmd
  8249.             select @upd_cmd = @valid_upd_cmd
  8250.             select @del_cmd = @valid_del_cmd
  8251.         end
  8252.         -- If pub sync_type is character mode bcp(1) 
  8253.         else if @sync_method = 1
  8254.         begin
  8255.             -- Parameterized command is not supported. Mask it off.
  8256.             select @status = @status & ~16
  8257.             if @ins_cmd is NULL  select @ins_cmd = 'SQL'
  8258.             if @upd_cmd is NULL  select @upd_cmd = 'SQL'
  8259.             if @del_cmd is NULL  select @del_cmd = 'SQL'
  8260.         end
  8261.  
  8262.         /*
  8263.         ** Parameter Check: @schema_option
  8264.         ** If Autogeneration of custom procedures is not enabled 
  8265.         ** then the default commands will be SQL
  8266.         */
  8267.         IF ((CONVERT(int, @schema_option) & 0x2) = 0)
  8268.         BEGIN
  8269.             if @ins_cmd is NULL  select @ins_cmd = 'SQL'
  8270.             if @upd_cmd is NULL  select @upd_cmd = 'SQL'
  8271.             if @del_cmd is NULL  select @del_cmd = 'SQL'
  8272.         END
  8273.               
  8274.         -- Autogenerate custom procedure names if not provided.
  8275.         -- Use destination table name as the base name by default. 
  8276.     /*    
  8277.         -- Use article name by default. If the name is too long or there's confliction,
  8278.         -- use guid (to prevent proc for diff art in diff pub has same name which cause problems
  8279.         -- when being subscribed by the same subscriber db.
  8280.         if ((@source_object is not NULL and len(@article) > 119) or
  8281.             (@source_object is NULL and len(@article) > 21)) or
  8282.             exists (select * from sysarticles where name = @article)
  8283.         begin
  8284.             set @guid = CONVERT(varbinary(16), LEFT(NEWID(),8))
  8285.             exec @retcode = master.dbo.xp_varbintohexstr @guid, @custom_proc_name OUTPUT
  8286.             if @@error <> 0 or @retcode <> 0
  8287.                 RETURN(1)
  8288.         end
  8289.         else
  8290.             set @custom_proc_name = @article
  8291.     */
  8292.  
  8293.         -- If no command then construct name 
  8294.         if @ins_cmd is NULL
  8295.         begin
  8296.             if (@status & 16) <> 0 -- parameterized
  8297.             begin
  8298.                 if @source_object is not NULL  -- 7.0 format
  8299.                     set @ins_cmd = N'CALL ' + convert (sysname, 'sp_MSins_' + @custom_proc_name)
  8300.                 else -- 6.x compatible
  8301.                     set @ins_cmd = N'CALL ' + convert(nvarchar(30), 'sp_MSins_' + @custom_proc_name)
  8302.             end
  8303.             else
  8304.                 select @ins_cmd = 'SQL'
  8305.         end
  8306.  
  8307.         if @del_cmd is NULL
  8308.         begin
  8309.             if (@status & 16) <> 0 -- parameterized
  8310.             begin
  8311.                 if @source_object is not NULL  -- 7.0 format
  8312.                     set @del_cmd = N'CALL ' + convert (sysname, 'sp_MSdel_' + @custom_proc_name)
  8313.                 else -- 6.x compatible
  8314.                     set @del_cmd = N'CALL ' + convert(nvarchar(30), 'sp_MSdel_' + @custom_proc_name)
  8315.             end
  8316.             else
  8317.                 select @del_cmd = 'SQL'
  8318.         end
  8319.  
  8320.         if @upd_cmd is NULL
  8321.         begin
  8322.             if (@status & 16) <> 0 -- parameterized
  8323.             begin
  8324.                 if @source_object is not NULL  -- 7.0 format
  8325.                     set @upd_cmd = N'MCALL ' + convert (sysname, 'sp_MSupd_' + @custom_proc_name)
  8326.                 else -- 6.x compatible
  8327.                     set @upd_cmd = N'CALL ' + convert(nvarchar(30), 'sp_MSupd_' + @custom_proc_name)
  8328.             end
  8329.             else
  8330.                 select @upd_cmd = 'SQL'
  8331.         end
  8332.  
  8333.         --
  8334.         -- Sync/QueuedTran
  8335.         -- Add guid column if not exists
  8336.         --
  8337.         if (@allow_sync_tran = 1 or @allow_queued_tran = 1)
  8338.         begin
  8339.             SELECT @MSrepl_tran_version_datatype = TYPE_NAME(xtype),
  8340.                 @colid = colid
  8341.             FROM dbo.syscolumns  
  8342.             WHERE id = @tabid AND name = 'msrepl_tran_version'
  8343.  
  8344.             if (@MSrepl_tran_version_datatype IS NULL)
  8345.             begin
  8346.                 --
  8347.                 -- column does not exist, add it
  8348.                 --
  8349.                 if exists (select * from sysobjects where id = @tabid and replinfo & @merge_pub_object_bit <>0)
  8350.                 begin
  8351.                     --if being merged, call stored procedure to add this column.
  8352.                     exec @retcode = sp_repladdcolumn @source_object=@source_table,
  8353.                                                      @column = 'msrepl_tran_version',
  8354.                                                      @typetext= 'uniqueidentifier not null default newid()'
  8355.                     if @@ERROR<>0 or @retcode<>0
  8356.                         return (1)
  8357.                 end
  8358.                 else
  8359.                 begin
  8360.                     exec ('alter table ' + @source_table + ' add msrepl_tran_version uniqueidentifier not null default newid()' )
  8361.                     IF @@ERROR <> 0 
  8362.                         RETURN (1)
  8363.                 end
  8364.             end
  8365.             else
  8366.             begin
  8367.                 --
  8368.                 -- column exists, it should be of type uniqueidentifier
  8369.                 --
  8370.                 if (@MSrepl_tran_version_datatype != 'uniqueidentifier')
  8371.                 begin
  8372.                     raiserror(21192, 16, -1) 
  8373.                     RETURN (1)
  8374.                 end
  8375.  
  8376.                 -- Create the default constraint if it is not there
  8377.                 if not exists (select * from sysconstraints where
  8378.                     id = @tabid and 
  8379.                     colid = @colid and
  8380.                     status & 5 = 5) -- default
  8381.                 begin 
  8382.                     declare @constraint_name sysname
  8383.                     select @constraint_name = 'MSrepl_tran_version_default_' + convert(nvarchar(10), @tabid)
  8384.                     if not exists (select * from sysobjects where name = @constraint_name)
  8385.                     begin
  8386.                         exec ('alter table ' + @source_table + 
  8387.                             ' add constraint ' + @constraint_name + 
  8388.                             ' default newid() for msrepl_tran_version')
  8389.                         if @@ERROR<>0 return 1
  8390.                     end
  8391.                 end
  8392.  
  8393.             end
  8394.         end
  8395.  
  8396.     /*  
  8397.         -- SyncTran
  8398.         -- Add timestamp column if not exists
  8399.         if @allow_sync_tran = 1 and @allow_queued_tran = 0 and ObjectProperty(@tabid, 'TableHasTimestamp') = 0
  8400.         begin
  8401.             exec ('alter table ' + @source_table + ' add msrepl_synctran_ts timestamp not null' )
  8402.             IF @@ERROR <> 0 
  8403.                 RETURN (1)
  8404.         end
  8405.     */
  8406.  
  8407.         -- if concurrent, must use stored procedures at subcriber when replicating commands
  8408.  
  8409.         if @sync_method IN (3,4) and 
  8410.            (lower(@del_cmd) not like N'%call%' or 
  8411.             lower(@ins_cmd) not like N'%call%' or
  8412.             lower(@upd_cmd) not like N'%call%' )
  8413.         begin
  8414.             raiserror( 21153, 16, -1, @article )
  8415.             return 1
  8416.         end
  8417.  
  8418.         -- Identity range support
  8419.             /*
  8420.         ** Parameter Check:  @allow_push.
  8421.         */
  8422.  
  8423.         IF @auto_identity_range IS NULL OR LOWER(@auto_identity_range collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  8424.             BEGIN
  8425.                 RAISERROR (14148, 16, -1, '@auto_identity_range')
  8426.                 RETURN (1)
  8427.             END
  8428.         IF LOWER(@auto_identity_range collate SQL_Latin1_General_CP1_CS_AS) = 'true' 
  8429.         begin
  8430.             if @allow_queued_tran = 0
  8431.             begin
  8432.                 raiserror(21231, 16 ,-1)
  8433.                 return 1
  8434.             end
  8435.             /*
  8436.             ** If you want to have identity support, @range and threshold can not be NULL
  8437.             */
  8438.             if (@pub_identity_range is NULL or @identity_range is NULL or @threshold is NULL)
  8439.                 begin
  8440.                     raiserror(21193, 16, -1)
  8441.                     return (1)
  8442.                 end
  8443.  
  8444.             if OBJECTPROPERTY(@tabid, 'tablehasidentity') <> 1
  8445.             begin
  8446.                 raiserror(21194, 16, -1)
  8447.                 return (1)
  8448.             end
  8449.  
  8450.             if @pub_identity_range <= 1 or @identity_range <= 1
  8451.             begin
  8452.                 raiserror(21232, 16 ,-1)
  8453.                 return 1
  8454.             end
  8455.  
  8456.             if @threshold < 1 or @threshold > 100
  8457.             begin
  8458.                 raiserror(21233, 16 ,-1)
  8459.                 return 1
  8460.             end
  8461.  
  8462.             declare @xtype int, @xprec int, @max_range bigint
  8463.             select @xtype=xtype, @xprec=xprec from syscolumns where id=@tabid and 
  8464.                 columnproperty(id, name, 'IsIdentity')=1
  8465.             select @max_range =
  8466.                     case @xtype when 52 then power((convert(bigint,2)), 8*2-1) - 1 --smallint 
  8467.                         when 48 then power((convert(bigint,2)), 8-1) - 1          --tinyint
  8468.                         when 56 then power((convert(bigint,2)), 8*4-1) - 1          --int
  8469.                         when 127 then power((convert(bigint,2)), 62) - 1 + power((convert(bigint,2)), 62)      --bigint
  8470.                            when 108 then power((convert(bigint,10)), @xprec)      --numeric
  8471.                            when 106 then power((convert(bigint,10)), @xprec)      --decimal
  8472.                      else
  8473.                         power((convert(bigint,2)), 62) + power((convert(bigint,2)), 62) - 1  -- defaulted to bigint
  8474.                     end
  8475.         
  8476.             if @pub_identity_range * 2 + @identity_range > (@max_range - IDENT_CURRENT(@source_table))
  8477.                 begin
  8478.                     raiserror(21290, 16, -1)
  8479.                     return (1)
  8480.                 end
  8481.  
  8482.             -- Set the range to negtive if incr of the identity is negtive
  8483.             if IDENT_INCR(@source_table) < 0
  8484.             begin
  8485.                 select @pub_identity_range = -1 * @pub_identity_range;
  8486.                 select @identity_range = -1 * @identity_range;
  8487.             end
  8488.  
  8489.             -- If the table is already published in queued but is not auto identity
  8490.             -- raiserror error
  8491.             if exists (select * from  sysarticles sa, sysarticleupdates au, syspublications pub where 
  8492.                 sa.objid = @tabid and
  8493.                 au.artid = sa.artid and
  8494.                 au.pubid = pub.pubid and
  8495.                 pub.allow_queued_tran = 1 and 
  8496.                 au.identity_support = 0)
  8497.             begin
  8498.                 raiserror (21240, 16, -1, @source_table)
  8499.                 return (1)
  8500.             end
  8501.  
  8502.             -- If the table is already published in queued and have different auto identity 
  8503.             -- range values, raise error.
  8504.             if exists (select * from MSpub_identity_range where objid=@tabid and 
  8505.             ((pub_range<>@pub_identity_range) or (range <> @identity_range) or (threshold <> @threshold)))
  8506.             begin
  8507.                 raiserror(21291, 16, -1)
  8508.                 return (1)
  8509.             end
  8510.         end
  8511.         else
  8512.         begin
  8513.             -- @auto_identity_range is false
  8514.             -- If the publication is queued and the table has published with auto identity
  8515.             -- already, raise error.
  8516.             if exists (select * from  sysarticles sa, sysarticleupdates au where 
  8517.                 sa.objid = @tabid and
  8518.                 au.artid = sa.artid and
  8519.                 au.identity_support = 1)
  8520.             begin
  8521.                 raiserror (21240, 16, -1, @source_table)
  8522.                 return (1)
  8523.             end
  8524.         end
  8525.  
  8526.         -- SQL insert doesn't work because we need to do 'set identity_insert on/off' 
  8527.         -- before and after the insert.
  8528.         -- The exception is snapshot publication.
  8529.         /* Queue now uses fixed commands. Message 21234 should be removed.
  8530.         if @allow_queued_tran = 1 and OBJECTPROPERTY(@tabid, 'tablehasidentity') = 1 and
  8531.             @ins_cmd = 'SQL' and @repl_freq <> 1
  8532.         begin
  8533.             raiserror(21234, 16, -1)
  8534.             return (1)
  8535.         end
  8536.         */
  8537.  
  8538.         -- Do not allow the table to be published by both merge and queued tran
  8539.         if @allow_queued_tran = 1
  8540.         begin
  8541.             if exists (select * from sysobjects where name = 'sysmergearticles')
  8542.             begin
  8543.                 if exists (select * from sysmergearticles where objid = @tabid)
  8544.                 begin
  8545.                     declare @obj_name sysname
  8546.                     select @obj_name = object_name(@tabid)
  8547.                     raiserror(21266, 16, -1, @obj_name)
  8548.                     return (1)
  8549.                 end
  8550.             end
  8551.         end
  8552.  
  8553.         /*
  8554.         **  Add article to sysarticles and update sysobjects category bit.
  8555.         */
  8556.         -- begin tran
  8557.         begin tran
  8558.         save TRAN sp_addarticle
  8559.  
  8560.         INSERT sysarticles (columns, creation_script, del_cmd, description,
  8561.             dest_table, filter, filter_clause, ins_cmd, name,
  8562.             objid, pre_creation_cmd, pubid,
  8563.             status, sync_objid, type, upd_cmd, schema_option,
  8564.             dest_owner)
  8565.         VALUES (0, @creation_script, @del_cmd, @description, @destination_table,
  8566.             @filterid, @filter_clause, @ins_cmd, @article, @tabid,
  8567.             @precmdid, @pubid, @status, @syncid, @typeid, @upd_cmd, @schema_option, 
  8568.             @destination_owner)
  8569.  
  8570.         IF @@ERROR <> 0
  8571.             goto UNDO
  8572.  
  8573.         SELECT @artid = @@IDENTITY
  8574.  
  8575.         UPDATE sysobjects SET replinfo =  replinfo |  @publish_bit
  8576.             WHERE id = (SELECT objid FROM sysarticles WHERE name = @article 
  8577.                 and pubid =  @pubid)
  8578.  
  8579.         IF @@ERROR <> 0
  8580.             goto UNDO
  8581.  
  8582.         IF @filter IS NOT NULL
  8583.         BEGIN
  8584.             EXEC dbo.sp_MSsetfilterparent @filter, @tabid
  8585.             IF @@ERROR <> 0
  8586.                 goto UNDO
  8587.         END
  8588.  
  8589.         EXEC dbo.sp_MSsetfilteredstatus @tabid
  8590.         IF @@ERROR <> 0
  8591.             goto UNDO
  8592.  
  8593.         /*
  8594.         ** Set all bits to '1' in the columns column to include all columns.
  8595.         */
  8596.  
  8597.         IF @vertical_partition = 'false'
  8598.         BEGIN
  8599.             EXECUTE @retcode  = dbo.sp_articlecolumn @publication, @article
  8600.             -- synctran
  8601.             , @refresh_synctran_procs = 0
  8602.              , @force_invalidate_snapshot = @force_invalidate_snapshot
  8603.       
  8604.             IF @@ERROR <> 0 OR @retcode <> 0
  8605.                 goto UNDO
  8606.         END
  8607.     
  8608.         /*
  8609.         ** 1. Set all bits to '1' for all columns in the primary key.
  8610.         ** 2. Set version column bit to 1 if the publication is synctran
  8611.         ** 3. For queued replication, set all column bits to 1 that do not allow
  8612.         **        NULL or DEFAULT value
  8613.         */
  8614.         ELSE
  8615.         BEGIN
  8616.             --
  8617.             -- for updating subscribers build a temp table
  8618.             -- to keep track of columns that are mandatory
  8619.             --
  8620.             if (@allow_sync_tran = 1 or @allow_queued_tran = 1)
  8621.             begin
  8622.                 create table #pktable(name sysname collate database_default)
  8623.             end
  8624.             
  8625.             --
  8626.             -- if it's a table, get the indid of the PK
  8627.             --
  8628.             if exists( select * from sysobjects where id = @tabid and xtype = 'U' )
  8629.             begin
  8630.                 SELECT @indid = indid FROM sysindexes
  8631.                 WHERE id = @tabid
  8632.                 AND (status & 2048) <> 0    /* PK index */
  8633.             end
  8634.             else  -- else it's a mview, use the CI (which, for a MV, must be unique)        
  8635.             begin
  8636.                 SELECT @indid = 1
  8637.             end
  8638.  
  8639.             /*
  8640.             **  First we'll figure out what the keys are.
  8641.             */
  8642.             SELECT @i = 1
  8643.  
  8644.             WHILE (@i <= 16)
  8645.             BEGIN
  8646.                 SELECT @pkkey = INDEX_COL(@source_table, @indid, @i)
  8647.                 if @pkkey is NULL
  8648.                     break
  8649.  
  8650.                 EXECUTE @retcode  = dbo.sp_articlecolumn @publication,
  8651.                     @article, @pkkey, 'add'
  8652.                     -- synctran
  8653.                     , @refresh_synctran_procs = 0
  8654.                     , @force_invalidate_snapshot = @force_invalidate_snapshot
  8655.                 IF @@ERROR <> 0 OR @retcode <> 0
  8656.                     goto UNDO
  8657.  
  8658.                 if (@allow_sync_tran = 1 or @allow_queued_tran = 1)
  8659.                     insert into #pktable(name) values(@pkkey)
  8660.                     
  8661.                 select @i = @i + 1
  8662.             END
  8663.  
  8664.             if (@allow_sync_tran = 1 or @allow_queued_tran = 1)
  8665.             BEGIN
  8666.                 --
  8667.                 -- The version column needs to go in
  8668.                 --
  8669.                 declare @version_col sysname
  8670.                 -- Get synctran column
  8671.                 select @version_col = 'msrepl_tran_version'
  8672.                 EXECUTE @retcode  = dbo.sp_articlecolumn @publication,
  8673.                     @article, @version_col, 'add'
  8674.                     -- synctran
  8675.                     , @refresh_synctran_procs = 0
  8676.                     , @force_invalidate_snapshot = @force_invalidate_snapshot
  8677.  
  8678.                 IF @@ERROR <> 0 OR @retcode <> 0
  8679.                     goto UNDO
  8680.  
  8681.                 insert into #pktable(name) values('msrepl_tran_version')
  8682.  
  8683.                 --
  8684.                 -- select the columns that are not IDENTITY columns
  8685.                 -- and do not allow NULL 
  8686.                 -- and do not have any DEFAULT constraints defined for them
  8687.                 -- and have not been processed already
  8688.                 -- (IDENTITY columns do not need to be referenced explicitly - 
  8689.                 -- which is like having a DEFAULT value so they can be excluded)
  8690.                 --
  8691.                 declare #htemp cursor local fast_forward for
  8692.                     select name from dbo.syscolumns 
  8693.                     where id = @tabid and isnullable = 0 
  8694.                         and cdefault = 0 
  8695.                         and ColumnProperty(id, name, N'IsIdentity') != 1
  8696.                         and name not in (select name from #pktable)    
  8697.  
  8698.                 open #htemp
  8699.                 fetch #htemp into @version_col
  8700.                 while (@@fetch_status = 0)
  8701.                 begin
  8702.                     EXECUTE @retcode  = dbo.sp_articlecolumn @publication,
  8703.                     @article, @version_col, 'add', @refresh_synctran_procs = 0
  8704.                     , @force_invalidate_snapshot = @force_invalidate_snapshot
  8705.  
  8706.                     IF (@@ERROR != 0 OR @retcode != 0)
  8707.                     BEGIN
  8708.                         close #htemp
  8709.                         deallocate #htemp
  8710.                         drop table #pktable
  8711.                         goto UNDO
  8712.                     END
  8713.                     fetch #htemp into @version_col
  8714.                 end
  8715.                 close #htemp
  8716.                 deallocate #htemp
  8717.                 drop table #pktable
  8718.             END
  8719.         end -- IF @vertical_partition = 'false' ELSE
  8720.  
  8721.         ------------------------------------------------------------------------------
  8722.         -- if table based article does not use a view for sync, create one and use it
  8723.         ------------------------------------------------------------------------------
  8724.  
  8725.         if @tabid = @syncid 
  8726.         begin
  8727.             -- generate view name
  8728.  
  8729.             declare @viewname varchar(255)
  8730.  
  8731.             set @guid = CONVERT(varbinary(16), LEFT(NEWID(),8))
  8732.             exec @retcode = master.dbo.xp_varbintohexstr @guid, @viewname OUTPUT
  8733.             if @@ERROR <> 0 OR @retcode <> 0
  8734.                 goto UNDO
  8735.             
  8736.             set @viewname = 'syncobj_' + @viewname
  8737.  
  8738.             -- create view for object synchronization
  8739.             if ((@allow_sync_tran = 1 or @allow_queued_tran = 1) 
  8740.                 and @vertical_partition = 'true')
  8741.             begin
  8742.                 --
  8743.                 -- vertical partition is true - this means we may not have the 
  8744.                 -- complete view yet - column could be added or dropped.
  8745.                 -- we do not want to validate the provided filter clause now
  8746.                 -- sp_articlefilter will be called explicitly later to add article 
  8747.                 -- filter and sp_articleview will be called finally to regenerate the 
  8748.                 -- view - and the filter validation will be done then for updating subscribers
  8749.                 --
  8750.                 exec @retcode = dbo.sp_articleview @publication, @article, @viewname, NULL
  8751.                     ,@force_invalidate_snapshot = @force_invalidate_snapshot
  8752.             end
  8753.             else
  8754.             begin
  8755.                 exec @retcode = dbo.sp_articleview @publication, @article, @viewname, @filter_clause
  8756.                     ,@force_invalidate_snapshot = @force_invalidate_snapshot
  8757.             end
  8758.             if @@ERROR <> 0 OR @retcode <> 0
  8759.                 goto UNDO
  8760.         end
  8761.  
  8762.         -- Need to change syscolumns status before generating sync procs because the
  8763.         -- status will be used to decide whether or not call set identity insert.
  8764.         IF LOWER(@auto_identity_range collate SQL_Latin1_General_CP1_CS_AS) = 'true' 
  8765.         begin
  8766.             -- Make the identity column as not for replication
  8767.             select @colid = null
  8768.             select @colid = colid from syscolumns  where
  8769.                  id = @tabid and
  8770.                  colstat & 0x0001 <> 0 and -- is identity
  8771.                  colstat & 0x0008 = 0 -- No 'not for repl' property
  8772.             if @colid is not null
  8773.             begin
  8774.                 exec @retcode  = dbo.sp_replupdateschema @source_table
  8775.                 -- Mark 'not for repl'
  8776.                 update syscolumns set colstat = colstat | 0x0008 where
  8777.                     id = @tabid and colid = @colid
  8778.                 -- Single to refresh the object cache.
  8779.                 exec @retcode  = dbo.sp_replupdateschema @source_table
  8780.                 IF @@ERROR <> 0 OR @retcode <> 0
  8781.                     goto UNDO
  8782.             end
  8783.         end
  8784.  
  8785.         /* 
  8786.         ** if @autogen_sync_procs_id is 1, autogen the sync tran procs, including name 
  8787.         */
  8788.         if @tabid > 0 and @autogen_sync_procs_id = 1
  8789.         begin
  8790.             declare @insproc sysname, @updproc sysname, @delproc sysname, @updtrig sysname
  8791.             select @insproc   = 'sp_MSsync_ins_'+ SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @pubid))
  8792.             select @updproc   = 'sp_MSsync_upd_'+ SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @pubid))
  8793.             select @delproc   = 'sp_MSsync_del_'+ SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @pubid))
  8794.             select @updtrig   = 'sp_MSsync_upd_trig_'+ SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @pubid))
  8795.  
  8796.             -- check uniqueness of names and revert to ugly guid-based name if friendly name already exists
  8797.             if exists (select name from sysobjects where name in (@insproc, @updproc, @delproc, @updtrig))
  8798.             begin
  8799.                 declare @guid_name nvarchar(36)
  8800.                 select @guid_name =  convert (nvarchar(36), newid())
  8801.                 -- remove '-' from guid name because rpc can't handle '-'
  8802.                 select @guid_name = replace (@guid_name,'-','_')
  8803.                 select @insproc = 'sp_MSsync_ins_' + @guid_name
  8804.                 select @updproc = 'sp_MSsync_upd_' + @guid_name
  8805.                 select @delproc = 'sp_MSsync_del_' + @guid_name
  8806.                 select @updtrig = 'sp_MSsync_upd_trig_' + @guid_name
  8807.             end
  8808.  
  8809.             if @insproc IS NULL
  8810.             begin
  8811.                 RAISERROR (14043, 11, -1, '@insproc')
  8812.                 goto UNDO
  8813.             end
  8814.  
  8815.             if @updproc IS NULL
  8816.             begin
  8817.                 RAISERROR (14043, 11, -1, '@updproc')
  8818.                 goto UNDO
  8819.             end
  8820.  
  8821.             if @delproc IS NULL
  8822.             begin
  8823.                 RAISERROR (14043, 11, -1, '@delproc')
  8824.                 goto UNDO
  8825.             end
  8826.  
  8827.  
  8828.             if @updtrig IS NULL
  8829.             begin
  8830.                 RAISERROR (14043, 11, -1, '@updtrig')
  8831.                 goto UNDO
  8832.             end
  8833.  
  8834.  
  8835.             exec @retcode = dbo.sp_articlesynctranprocs @publication, @article, @insproc, @updproc, @delproc, true, @updtrig
  8836.  
  8837.             IF @@ERROR <> 0 OR @retcode <> 0
  8838.                 goto UNDO
  8839.         end
  8840.         -- end SyncTran
  8841.  
  8842.         -- Generate the conflict table and conflict proc for Queued Tran case
  8843.         if (@allow_queued_tran = 1)
  8844.         begin
  8845.             exec @retcode = dbo.sp_MSmakeconflicttable @article, @publication, 0
  8846.             IF @@ERROR <> 0 OR @retcode <> 0
  8847.                 goto UNDO
  8848.             exec @retcode = dbo.sp_MSmaketrancftproc @article, @publication
  8849.             IF @@ERROR <> 0 OR @retcode <> 0
  8850.                 goto UNDO
  8851.         end 
  8852.  
  8853.         IF LOWER(@auto_identity_range collate SQL_Latin1_General_CP1_CS_AS) = 'true' 
  8854.         begin
  8855.             -- Have to do the update below after sync proc generation since
  8856.             -- it will insert row to sysarticleupdates
  8857.             update sysarticleupdates set identity_support = 1 where artid = @artid
  8858.             IF @@ERROR <> 0
  8859.                 goto UNDO
  8860.             
  8861.             -- It is possible that the table is already being published. If so
  8862.             -- keep the old identity range values.
  8863.             if not exists (select * from MSpub_identity_range where objid = @tabid)
  8864.             begin
  8865.                 insert into MSpub_identity_range (objid, range, pub_range, current_pub_range, last_seed, threshold) 
  8866.                     values (@tabid, @identity_range, @pub_identity_range, @pub_identity_range, null, @threshold) 
  8867.                 IF @@ERROR <> 0
  8868.                     goto UNDO
  8869.             
  8870.                 -- Call stored procedure to reconcile identity range
  8871.                 exec @retcode = dbo.sp_MSpub_adjust_identity @artid = @artid
  8872.                 IF @@ERROR <> 0 OR @retcode <> 0
  8873.                     goto UNDO
  8874.             end                    
  8875.         end -- IF LOWER(@auto_identity_range collate SQL_Latin1_General_CP1_CS_AS) = 'true' 
  8876.     END -- End of the else block handle table articles.
  8877.  
  8878.     -- 0x00001000 collation
  8879.     -- 0x00002000 extended property
  8880.     -- @schema_option is already padded out at the beginning of this procedure
  8881.  
  8882.     SELECT @schema_option_int = fn_replgetbinary8lodword(@schema_option)
  8883.     IF ((@schema_option_int & 0x00001000 <>0 ) or 
  8884.         (@schema_option_int & 0x00002000 <> 0 ))
  8885.         select @backward_comp_level = 40
  8886.     if @backward_comp_level > 10
  8887.         update syspublications set backward_comp_level = @backward_comp_level where pubid = @pubid
  8888.  
  8889.     /*
  8890.     ** Get distribution server information for remote RPC call.
  8891.     */
  8892.     EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  8893.        @distribdb   = @distribdb OUTPUT
  8894.     IF @@ERROR <> 0 or @retcode <> 0
  8895.         goto UNDO
  8896.  
  8897.     SELECT @dbname =  DB_NAME()
  8898.     
  8899.     SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  8900.         '.dbo.sp_MSadd_article'
  8901.     EXECUTE @retcode = @distproc
  8902.         @publisher = @@SERVERNAME,
  8903.         @publisher_db = @dbname,
  8904.         @publication = @publication,
  8905.         @article = @article,
  8906.         @article_id = @artid,
  8907.         @destination_object = @destination_table,
  8908.         @source_owner = @source_owner,
  8909.         @source_object = @bak_source,
  8910.         @description = @description
  8911.  
  8912.     IF @@ERROR <> 0 OR @retcode <> 0
  8913.         goto UNDO
  8914.     
  8915.     /* If the publication is immediate_sync type
  8916.     ** 1. Change the immediate_sync_ready status to false 
  8917.     ** 2. Add a virtual subscription on the article 
  8918.     ** 3. Add subscriptions for all the subscriber
  8919.     ** that have no_sync subscriptions on the publication
  8920.     **
  8921.     ** Note: Subscriptions for subscribers that have automatic sync subscriptions
  8922.     ** on the publication will be added by snasphot agent.
  8923.     */
  8924.     if EXISTS (SELECT *    FROM syspublications WHERE
  8925.         name = @publication    AND
  8926.         immediate_sync = 1 )
  8927.     BEGIN
  8928.         EXECUTE @retcode  = dbo.sp_addsubscription 
  8929.             @publication = @publication, 
  8930.             @article = @article, 
  8931.             @subscriber = NULL, 
  8932.             @destination_db = 'virtual', 
  8933.             @sync_type = 'automatic', 
  8934.             @status = NULL, 
  8935.             @reserved = 'internal'
  8936.         IF @@ERROR <> 0 OR @retcode <> 0
  8937.             GOTO UNDO
  8938.  
  8939.         -- Note: We have to add the subscriptions to the new article before 
  8940.         -- the virtual subscriptions being activated!!!! Otherwise, the snapshot 
  8941.         -- transactions may be skipped by dist agents.
  8942.         EXECUTE @retcode  = dbo.sp_refreshsubscriptions @publication
  8943.  
  8944.         IF @@ERROR <> 0 OR @retcode <> 0
  8945.             GOTO UNDO
  8946.         
  8947.         -- Have to call this stored procedure to invalidate existing snapshot
  8948.         -- if there are any. 
  8949.         EXECUTE @retcode  = dbo.sp_MSreinit_article
  8950.             @publication = @publication, 
  8951.             -- Virtual subscriptions of all the articles will be deactivated.
  8952.             -- @article = @article,
  8953.             @need_new_snapshot = 1,
  8954.             @force_invalidate_snapshot = @force_invalidate_snapshot    
  8955.         IF @@ERROR <> 0 OR @retcode <> 0
  8956.             GOTO UNDO
  8957.     END
  8958.  
  8959.     COMMIT TRANSACTION
  8960.     return 0
  8961. UNDO:
  8962.     if @@trancount > 0
  8963.     begin
  8964.         ROLLBACK TRANSACTION sp_addarticle
  8965.         commit tran
  8966.     end
  8967.     RETURN (1)
  8968. go
  8969.  
  8970. /*
  8971. ** Create replication stored procedures.
  8972. ** Part 1:  create codependent procedures.
  8973. */
  8974.  
  8975. EXEC dbo.sp_MS_marksystemobject sp_addarticle
  8976. GO
  8977.  
  8978. print ''
  8979. print 'Creating procedure sp_MSgettranconflictname'
  8980. go
  8981. CREATE PROCEDURE sp_MSgettranconflictname (
  8982. @publication sysname,
  8983. @source_object nvarchar(540),
  8984. @str_prefix nvarchar(30) = NULL,
  8985. @conflict_table sysname = NULL OUTPUT)
  8986. AS
  8987. begin
  8988.     declare @objid                 int
  8989.     declare @retcode            int
  8990.     declare @object_name        sysname
  8991.     declare @name_out            sysname
  8992.     declare @pubid                int
  8993.     declare @article            sysname
  8994.     declare @artid                int
  8995.     declare @prefixlen            int
  8996.  
  8997.     if (@str_prefix is NULL)
  8998.         select @str_prefix = 'conflict_'
  8999.  
  9000.     select @prefixlen = len(@str_prefix)
  9001.  
  9002.     select @pubid=pubid from syspublications 
  9003.         where name=@publication
  9004.  
  9005.     select @objid = object_id(@source_object)
  9006.     select @artid = artid, @article=name from sysarticles 
  9007.         where objid = @objid and pubid=@pubid
  9008.  
  9009.     if len(@publication) + len(@article) > 128 - @prefixlen -1     -- SYSNAME minus prefix len
  9010.     begin
  9011.         select @object_name = @str_prefix + 
  9012.             convert(nvarchar(59), @publication) + 
  9013.             '_' + convert(nvarchar(59), @article)
  9014.     end
  9015.     else
  9016.     begin
  9017.         select @object_name = @str_prefix + @publication + '_' + @article
  9018.     end
  9019.     select @conflict_table = @object_name
  9020.     exec @retcode = dbo.sp_MSuniqueobjectname @object_name, @conflict_table OUTPUT
  9021. end
  9022. GO
  9023. EXEC dbo.sp_MS_marksystemobject sp_MSgettranconflictname
  9024. GO
  9025.  
  9026. print ''
  9027. print 'Creating procedure sp_MSmaketrancftproc'
  9028. go
  9029.  
  9030. create procedure sp_MSmaketrancftproc (
  9031.     @article sysname, 
  9032.     @publication sysname,
  9033.     @is_debug bit=0)
  9034. as
  9035. BEGIN
  9036. declare @source_table nvarchar(540)
  9037.         ,@owner sysname
  9038.         ,@procname sysname
  9039.         ,@source_objid int
  9040.         ,@artid int
  9041.         ,@pubid int
  9042.         ,@conflict_tableid int
  9043.         ,@conflict_table    sysname
  9044.         ,@conflict_proc_id int
  9045.         ,@indid int
  9046.         ,@indkey int
  9047.         ,@ind_col_name sysname
  9048.         ,@qualname   nvarchar(540)
  9049.         ,@destqualname   nvarchar(540)
  9050.         ,@destowner sysname
  9051.         ,@dbname sysname
  9052.         ,@retcode smallint
  9053.         ,@retain_varname int
  9054.  
  9055. declare @colid        int
  9056.         ,@colname    sysname
  9057.         ,@coltype    sysname
  9058.         ,@ccoltype    sysname
  9059.         ,@rowcnt    int
  9060.  
  9061. declare @argtabempty    bit
  9062.         ,@seltabempty    bit
  9063.         ,@sel2tabempty    bit
  9064.         ,@valtabempty     bit
  9065.         ,@paramtabempty    bit
  9066.         ,@where_clausetabempty bit
  9067.         ,@decltabempty bit
  9068.         ,@assigntabempty bit
  9069.         ,@compinsertabempty bit
  9070.  
  9071. declare @argterm    nvarchar(4000)
  9072.         ,@selterm    nvarchar(4000)
  9073.         ,@sel2term    nvarchar(4000)
  9074.         ,@updterm    nvarchar(4000)
  9075.         ,@valterm     nvarchar(4000)
  9076.         ,@paramterm    nvarchar(4000)
  9077.         ,@where_term nvarchar(4000)
  9078.         ,@declterm    nvarchar(4000)
  9079.         ,@assignterm nvarchar(4000)
  9080.         ,@compinsterm nvarchar(4000)
  9081.  
  9082. declare @cmd        nvarchar(4000)
  9083.  
  9084. set nocount on
  9085.  
  9086. --
  9087. -- prepare the proc name and get the other parameters
  9088. --
  9089. select @artid = a.artid, @pubid = a.pubid, @source_table = object_name(a.objid), 
  9090.         @source_objid = a.objid, @destowner = a.dest_owner 
  9091. from sysarticles a, syspublications p
  9092.         where a.name = @article and
  9093.               p.name = @publication and
  9094.               a.pubid = p.pubid
  9095.  
  9096. -- Get the object owner name
  9097. select @owner = u.name 
  9098. from sysusers u, sysobjects o 
  9099. where o.id = @source_objid and o.uid = u.uid
  9100.  
  9101. --
  9102. -- Prepare the proc name 
  9103. -- The source table should be owner qualified
  9104. --
  9105. select @source_table = QUOTENAME(@owner) + N'.' + QUOTENAME(@source_table)
  9106. exec @retcode = sp_MSgettranconflictname @publication=@publication, 
  9107.                     @source_object= @source_table, 
  9108.                     @str_prefix='sp_MScft_', 
  9109.                     @conflict_table=@procname OUTPUT
  9110.  
  9111. --
  9112. -- The conflict table should exist before we do any conflict procs
  9113. --
  9114. select @conflict_tableid = conflict_tableid, 
  9115.         @conflict_table = OBJECT_NAME(conflict_tableid) 
  9116. from sysarticleupdates
  9117. where artid = @artid and pubid = @pubid
  9118. if ( @conflict_tableid is NULL)
  9119.     return (1)
  9120. --
  9121. -- To check if specified object exists in current database
  9122. --
  9123. select @qualname = case when (@owner is null or @owner = ' ') then QUOTENAME(@conflict_table)
  9124.                     else QUOTENAME(@owner) + N'.' + QUOTENAME(@conflict_table) end
  9125. if (object_id(@qualname) is NULL)
  9126.     return (1)
  9127.  
  9128. --
  9129. -- The source table should have an unique index
  9130. --
  9131. exec @indid = dbo.sp_MStable_has_unique_index @source_objid
  9132. if (@indid = 0)
  9133.     return (1)
  9134.  
  9135. --
  9136. -- Get all the columns participating in the index of the source table
  9137. --
  9138. create table #indcoltab ( colname sysname collate database_default )
  9139. select @indkey = 1;
  9140. while (@indkey <= 16)
  9141. begin
  9142.     select @ind_col_name = index_col(@source_table, @indid, @indkey)
  9143.     if (@ind_col_name is not NULL) 
  9144.         insert into #indcoltab(colname) values(@ind_col_name)
  9145.     else
  9146.         select @indkey = 16
  9147.  
  9148.     select @indkey = @indkey + 1
  9149. end
  9150.  
  9151. --
  9152. -- prepare destination table name (required for decentralized conflict processing)
  9153. --
  9154. select @destqualname = case when (@destowner is null or @destowner = ' ') 
  9155.                     then QUOTENAME(@conflict_table)
  9156.                     else QUOTENAME(@destowner) + N'.' + QUOTENAME(@conflict_table) end
  9157.  
  9158. -- build the lists
  9159. select @argtabempty = 1
  9160.     ,@valtabempty = 1
  9161.     ,@paramtabempty = 1
  9162.     ,@seltabempty = 1
  9163.     ,@sel2tabempty = 1
  9164.     ,@decltabempty = 1
  9165.     ,@assigntabempty = 1
  9166.     ,@where_clausetabempty = 1
  9167.     ,@compinsertabempty = 1
  9168.  
  9169. create table #argtab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9170. create table #valtab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9171. create table #paramtab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9172. create table #seltab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9173. create table #sel2tab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9174. create table #decltab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9175. create table #assigntab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9176. create table #where_clausetab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9177. create table #compinstab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9178.  
  9179. -- some predefined declares and assignments
  9180. select @cmd = N'
  9181.     declare @reinit_code int, @subwins_code int, @pubwins_code int, @qcfttabrowid uniqueidentifier
  9182.             ,@retcode smallint, @compcmd nvarchar(4000), @centralized_conflicts bit'
  9183. insert into #decltab(procedure_text) values(@cmd)
  9184. select @decltabempty = 0
  9185.     
  9186. select @cmd = N'
  9187.     select @reinit_code = 3
  9188.             ,@subwins_code = 2
  9189.             ,@pubwins_code = 1
  9190.             ,@qcfttabrowid = NEWID()'
  9191. insert into #assigntab(procedure_text) values(@cmd)
  9192. select @cmd = N'
  9193.     select @centralized_conflicts = centralized_conflicts
  9194.     from dbo.syspublications where pubid = ' + cast(@pubid as nvarchar)
  9195. insert into #assigntab(procedure_text) values(@cmd)
  9196. select @assigntabempty = 0
  9197.     
  9198. declare #argcursor cursor local FAST_FORWARD FOR 
  9199.         select colid
  9200.         from syscolumns
  9201.         where iscomputed = 0 and id=@conflict_tableid 
  9202.         order by colid
  9203. FOR READ ONLY
  9204.  
  9205. select @retain_varname = 0
  9206. open #argcursor
  9207. fetch #argcursor into @colid
  9208. while (@@FETCH_STATUS = 0)
  9209. begin
  9210.     --
  9211.     -- Get the column name and column type
  9212.     --
  9213.     exec dbo.sp_MSget_type @conflict_tableid, @colid, @colname output, @coltype OUTPUT
  9214.     if (@@ERROR<>0 or @retcode<>0)
  9215.         return (1)
  9216.  
  9217.     --
  9218.     -- skip this specific column or if type is not returned
  9219.     --
  9220.     if ((@coltype IS NULL) or (LOWER(@colname) = 'qcfttabrowid'))
  9221.     begin
  9222.         -- do the next fetch and continue
  9223.         fetch #argcursor into @colid
  9224.         continue    
  9225.     end
  9226.         
  9227.     exec dbo.sp_MSget_colinfo @conflict_tableid, @colid, NULL, 0, NULL, @ccoltype output
  9228.     if (@@ERROR<>0 or @retcode<>0)
  9229.         return (1)
  9230.  
  9231.     --
  9232.     -- parameterize the vars that are the column values of the source
  9233.     -- table. For the columns that are specific to the conflict table
  9234.     -- retain specific names for the vars
  9235.     --
  9236.     if (LOWER(@colname collate SQL_Latin1_General_CP1_CS_AS) = 'origin_datasource')
  9237.         select @retain_varname = @colid
  9238.  
  9239.     if (@retain_varname = 0)
  9240.         select @argterm = N'@param' + cast(@colid as nvarchar) 
  9241.     else
  9242.         select @argterm = N'@' + @colname
  9243.         
  9244.     select @valterm = quotename(@colname)
  9245.     select @paramterm = @argterm
  9246.     select @updterm = @valterm + N' = ' + @argterm
  9247.  
  9248.     if (@retain_varname = 0)
  9249.     begin
  9250.         select @selterm = @paramterm + N' = ' + @valterm
  9251.         select @sel2term = @paramterm + N' = case when ' + @paramterm + 
  9252.                     N' is NULL then ' + @valterm + N' else ' + @paramterm + N' end'
  9253.     end
  9254.     else
  9255.     begin
  9256.         select @selterm = NULL
  9257.         select @sel2term = NULL
  9258.     end
  9259.      
  9260.     select @argterm = @argterm + N' ' + @coltype
  9261.  
  9262.     -- Check if this is part of primary key    / unique index
  9263.     if (@colname in ( select colname from #indcoltab ) )
  9264.     begin
  9265.         -- this key assignment becomes part of where clause
  9266.         select @where_term = @updterm
  9267.         select @updterm = NULL
  9268.         select @selterm = NULL
  9269.         select @sel2term = NULL
  9270.     end
  9271.     else
  9272.         select @where_term = NULL
  9273.  
  9274.     -- special columns - process them as local var
  9275.     if (LOWER(@colname collate SQL_Latin1_General_CP1_CS_AS) = 'insertdate' )
  9276.     begin
  9277.         select @declterm = N'
  9278.     declare ' + @argterm
  9279.         select @assignterm = N'
  9280.     select ' + @paramterm + N' = GETDATE()'
  9281.         select @argterm = NULL
  9282.     end
  9283.     else if (LOWER(@colname collate SQL_Latin1_General_CP1_CS_AS) = 'pubid' )
  9284.     begin
  9285.         select @declterm = N'
  9286.     declare ' + @argterm
  9287.         select @assignterm = N'
  9288.     select ' + @paramterm + N' = ' + cast(@pubid as nvarchar)
  9289.         select @argterm = NULL
  9290.     end
  9291.     else
  9292.     begin
  9293.         select @declterm = NULL
  9294.         select @assignterm = NULL
  9295.     end
  9296.  
  9297.     -- build the term for compensating insert
  9298.     if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'varchar')
  9299.         select @compinsterm = N' '''''' + master.dbo.fn_MSgensqescstr(' + @valterm + N') collate database_default + '''''''' '
  9300.     else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'nvarchar')
  9301.         select @compinsterm = N' N'''''' + master.dbo.fn_MSgensqescstr(' + @valterm + N') collate database_default + '''''''' '
  9302.     else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'char')
  9303.         select @compinsterm = N' '''''' + master.dbo.fn_MSgensqescstr(CAST(RTRIM(' + @valterm + N') as nvarchar(4000))) collate database_default + '''''''' '
  9304.     else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'nchar')
  9305.         select @compinsterm = N' N'''''' + master.dbo.fn_MSgensqescstr(CAST(RTRIM(' + @valterm + N') as nvarchar(4000))) collate database_default + '''''''' '
  9306.     else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('binary','varbinary'))
  9307.         select @compinsterm = N' '' + master.dbo.fn_varbintohexstr(' + @valterm + N') collate database_default ' 
  9308.     else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('bit','bigint','int','smallint','tinyint','float','real','decimal','numeric'))
  9309.         select @compinsterm = N' '' + CAST(' + @valterm + N' as nvarchar) '
  9310.     else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('money','smallmoney'))
  9311.         select @compinsterm = N' '' + CONVERT(nvarchar(40),' + @valterm + N', 2) '
  9312.     else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'uniqueidentifier')
  9313.         select @compinsterm = N' '''''' + CAST(' + @valterm + N' as nvarchar(40)) + '''''''' '
  9314.     else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('datetime','smalldatetime'))
  9315.         select @compinsterm = N' '''''' + CONVERT(nvarchar(40), ' + @valterm + N', 112) + N'' ''  + CONVERT(nvarchar(40), ' + @valterm + N', 114) + '''''''' '
  9316.     else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'sql_variant')
  9317.         select @compinsterm = N' '' + master.dbo.fn_sqlvarbasetostr(' + @valterm + N' ) collate database_default '
  9318.     else
  9319.         select @compinsterm = N' '' + CAST(' + @valterm + N' as nvarchar) '
  9320.     
  9321.     -- Now append to the various lists
  9322.     if (@argterm is NOT NULL)
  9323.     begin        
  9324.         if (@argtabempty = 1)
  9325.         begin
  9326.             select @argtabempty = 0
  9327.             select @cmd = N'
  9328.     ' + @argterm
  9329.         end
  9330.         else
  9331.             select @cmd = N',
  9332.     ' + @argterm
  9333.         insert into #argtab(procedure_text) values(@cmd)
  9334.     end
  9335.     if (@valterm is NOT NULL)
  9336.     begin
  9337.         if (@valtabempty = 1)
  9338.         begin
  9339.             select @valtabempty = 0
  9340.             select @cmd = @valterm
  9341.         end
  9342.         else
  9343.             select @cmd = N', ' + @valterm
  9344.         insert into #valtab(procedure_text) values(@cmd)
  9345.     end
  9346.     if (@paramterm is NOT NULL)
  9347.     begin
  9348.         if (@paramtabempty = 1)
  9349.         begin
  9350.             select @paramtabempty = 0
  9351.             select @cmd = @paramterm
  9352.         end
  9353.         else
  9354.             select @cmd = N', ' + @paramterm
  9355.         insert into #paramtab(procedure_text) values(@cmd)
  9356.     end
  9357.     if (@selterm is NOT NULL)
  9358.     begin
  9359.         if (@seltabempty = 1)
  9360.         begin
  9361.             select @seltabempty = 0
  9362.             select @cmd = N'
  9363.         ' + @selterm
  9364.         end
  9365.         else
  9366.             select @cmd = N'
  9367.         ,' + @selterm        
  9368.         insert into #seltab(procedure_text) values(@cmd)
  9369.     end
  9370.     if (@sel2term is NOT NULL)
  9371.     begin
  9372.         if (@sel2tabempty = 1)
  9373.         begin
  9374.             select @sel2tabempty = 0
  9375.             select @cmd = N'
  9376.         ' + @sel2term
  9377.         end
  9378.         else
  9379.             select @cmd = N'
  9380.         ,' + @sel2term        
  9381.         insert into #sel2tab(procedure_text) values(@cmd)
  9382.     end    
  9383.     if (@where_term is NOT NULL)
  9384.     begin
  9385.         if (@where_clausetabempty = 1)
  9386.         begin
  9387.             select @where_clausetabempty = 0
  9388.             select @cmd = @where_term
  9389.         end
  9390.         else
  9391.             select @cmd = N' AND 
  9392.             ' + @where_term
  9393.         insert into #where_clausetab(procedure_text) values(@cmd)
  9394.     end
  9395.     if (@declterm is NOT NULL)
  9396.     begin
  9397.         select @cmd = @declterm + N'
  9398.     '
  9399.         insert into #decltab(procedure_text) values(@cmd)
  9400.     end        
  9401.  
  9402.     if (@assignterm is NOT NULL)
  9403.     begin
  9404.         select @cmd = @assignterm + N'
  9405.     '
  9406.         insert into #assigntab(procedure_text) values(@cmd)
  9407.     end        
  9408.  
  9409.     if (@compinsterm is NOT NULL)
  9410.     begin
  9411.         if (@compinsertabempty = 1)
  9412.         begin
  9413.             select @compinsertabempty = 0
  9414.             select @cmd = N' + ISNULL(''' + @compinsterm + N', ''null'')'
  9415.         end
  9416.         else
  9417.             select @cmd = N' + ISNULL('',' + @compinsterm + N', ''null'')'
  9418.         insert into #compinstab(procedure_text) values(@cmd)
  9419.     end
  9420.     
  9421.     -- do the next fetch
  9422.     fetch #argcursor into @colid
  9423.  
  9424. end
  9425. close #argcursor
  9426. deallocate #argcursor
  9427. drop table #indcoltab
  9428.  
  9429. --
  9430. -- generation phase
  9431. --
  9432. BEGIN TRAN sp_MSmaketrancftproc
  9433.  
  9434. -- create temp table to select the command text out of
  9435. if exists (select * from sysobjects where name = 'tempcmd' and uid = user_id('dbo'))
  9436.         drop table dbo.tempcmd
  9437. create table dbo.tempcmd ( c1 int identity NOT NULL, cmdtext nvarchar(4000) NULL)
  9438.  
  9439. -- create header
  9440. insert into  dbo.tempcmd(cmdtext) 
  9441. values(N'create procedure '+QUOTENAME(@owner)+ N'.'+ QUOTENAME(@procname) + N'( 
  9442. ')
  9443.  
  9444. -- insert the arglist
  9445. insert into dbo.tempcmd(cmdtext) select procedure_text from #argtab order by c1 
  9446. insert into dbo.tempcmd(cmdtext) values(N' ,@subcriber sysname = NULL, @subdb sysname = NULL )
  9447. as
  9448. begin
  9449. ')
  9450.  
  9451. -- insert the declare list
  9452. insert into dbo.tempcmd(cmdtext) select procedure_text from #decltab order by c1 
  9453. insert into dbo.tempcmd(cmdtext) values(N'
  9454. ')
  9455.  
  9456. -- insert the assignment list (for declared vars)
  9457. insert into dbo.tempcmd(cmdtext) select procedure_text from #assigntab order by c1
  9458.  
  9459. -- do the select for the case where we need to retain values of publisher
  9460. insert into dbo.tempcmd(cmdtext) values(N'
  9461.     if (@reason_code = @subwins_code)
  9462.     begin
  9463.         select ')
  9464. insert into dbo.tempcmd(cmdtext) select procedure_text from #seltab order by c1
  9465. insert into dbo.tempcmd(cmdtext) values(N'
  9466.         from ' + @source_table + N' where ')
  9467. insert into dbo.tempcmd(cmdtext) select procedure_text from #where_clausetab order by c1
  9468. insert into dbo.tempcmd(cmdtext) values(N'
  9469.     end')
  9470.  
  9471. insert into dbo.tempcmd(cmdtext) values(N'
  9472.     else
  9473.     begin
  9474.         select ')
  9475.     
  9476. insert into dbo.tempcmd(cmdtext) select procedure_text from #sel2tab order by c1
  9477. insert into dbo.tempcmd(cmdtext) values(N'
  9478.         from ' + @source_table + N' where ')
  9479. insert into dbo.tempcmd(cmdtext) select procedure_text from #where_clausetab order by c1
  9480. insert into dbo.tempcmd(cmdtext) values(N'
  9481.     end
  9482. ')
  9483.  
  9484. --
  9485. -- insert the conflict row in the publisher cft table
  9486. --
  9487. insert into dbo.tempcmd(cmdtext) values(N'
  9488.     insert into ' + @qualname + N'(')
  9489. insert into dbo.tempcmd(cmdtext) select procedure_text from #valtab order by c1
  9490. insert into dbo.tempcmd(cmdtext) values(N',[qcfttabrowid]) 
  9491.     values (')
  9492. insert into dbo.tempcmd(cmdtext) select procedure_text from #paramtab order by c1
  9493. insert into dbo.tempcmd(cmdtext) values(N',@qcfttabrowid)
  9494. ')
  9495.  
  9496. --
  9497. -- generate compensating command decentralized logging
  9498. -- depending on the number of columns, we will split the compensating
  9499. -- command into several compensating commands
  9500. --
  9501. select @rowcnt = 0, @compinsertabempty = 1
  9502. select @cmd = N'
  9503.     if (@centralized_conflicts = 0)
  9504.     begin
  9505.         select @compcmd = N''insert into ' + master.dbo.fn_MSgensqescstr(@destqualname) collate database_default + N' ( '
  9506. insert into dbo.tempcmd(cmdtext) values(@cmd)
  9507.  
  9508. declare #htempcur cursor local for
  9509.     select master.dbo.fn_MSgensqescstr(procedure_text) from #valtab order by c1
  9510. for read only
  9511.  
  9512. open #htempcur
  9513. fetch #htempcur into @compinsterm
  9514. while (@@fetch_status = 0)
  9515. begin
  9516.     insert into dbo.tempcmd(cmdtext) select @compinsterm
  9517.     select @rowcnt = @rowcnt + 1
  9518.  
  9519.     --
  9520.     -- if we have processed 10 terms then split the command
  9521.     --
  9522.     if (@rowcnt > 9)
  9523.     begin
  9524.         select @cmd = N'''
  9525.         from ' + @qualname + N' where qcfttabrowid = @qcfttabrowid and tranid = @tranid' 
  9526.         insert into dbo.tempcmd(cmdtext) values(@cmd)        
  9527.     
  9528.         select @cmd = N'
  9529.         exec @retcode = dbo.sp_MSadd_compensating_cmd @subcriber, @subdb, @compcmd, ' 
  9530.             + CAST(@artid as nvarchar(10)) + N', ' + CAST(@pubid as nvarchar(10)) + N',1,0,'
  9531.             + CAST(@compinsertabempty as nvarchar(4)) + N'
  9532.         if (@@error != 0 or @retcode != 0)
  9533.             return 1 
  9534.         
  9535.         select @compcmd = N''' 
  9536.         insert into dbo.tempcmd(cmdtext) values(@cmd)
  9537.         select @rowcnt = 0, @compinsertabempty = 0
  9538.     end
  9539.     fetch #htempcur into @compinsterm
  9540. end
  9541.  
  9542. close #htempcur
  9543. deallocate #htempcur
  9544.  
  9545. insert into dbo.tempcmd(cmdtext) values(N', [qcfttabrowid] ) values ('' ')
  9546. select @rowcnt = @rowcnt + 1
  9547.  
  9548. declare #htempcur cursor local for
  9549.     select procedure_text from #compinstab order by c1
  9550. for read only
  9551.  
  9552. open #htempcur
  9553. fetch #htempcur into @compinsterm
  9554. while (@@fetch_status = 0)
  9555. begin
  9556.     insert into dbo.tempcmd(cmdtext) select @compinsterm
  9557.     select @rowcnt = @rowcnt + 1
  9558.  
  9559.     --
  9560.     -- if we have processed 10 terms then split the command
  9561.     --
  9562.     if (@rowcnt > 9)
  9563.     begin
  9564.         select @cmd = N'
  9565.         from ' + @qualname + N' where qcfttabrowid = @qcfttabrowid and tranid = @tranid' 
  9566.         insert into dbo.tempcmd(cmdtext) values(@cmd)        
  9567.     
  9568.         select @cmd = N'
  9569.         exec @retcode = dbo.sp_MSadd_compensating_cmd @subcriber, @subdb, @compcmd, ' 
  9570.             + CAST(@artid as nvarchar(10)) + N', ' + CAST(@pubid as nvarchar(10)) + N',1,0,'
  9571.             + CAST(@compinsertabempty as nvarchar(4)) + N'
  9572.         if (@@error != 0 or @retcode != 0)
  9573.             return 1 
  9574.         
  9575.         select @compcmd = N'' ''' 
  9576.         insert into dbo.tempcmd(cmdtext) values(@cmd)
  9577.         select @rowcnt = 0, @compinsertabempty = 0
  9578.     end
  9579.     fetch #htempcur into @compinsterm
  9580. end
  9581.  
  9582. close #htempcur
  9583. deallocate #htempcur
  9584.  
  9585. --
  9586. -- script the remaining compensating command
  9587. --
  9588. select @cmd = N' + '', '''''' + CAST([qcfttabrowid] as nvarchar(40)) + '''''''' + N'' ) ''
  9589.         from ' + @qualname + N' where qcfttabrowid = @qcfttabrowid and tranid = @tranid' 
  9590. insert into dbo.tempcmd(cmdtext) values(@cmd)
  9591. select @rowcnt = @rowcnt + 1
  9592.  
  9593. select @cmd = N'
  9594.         exec @retcode = dbo.sp_MSadd_compensating_cmd @subcriber, @subdb, @compcmd, ' 
  9595.             + CAST(@artid as nvarchar(10)) + N', ' + CAST(@pubid as nvarchar(10)) + N',0,0,'
  9596.             + CAST(@compinsertabempty as nvarchar(4)) + N'
  9597.         if (@@error != 0 or @retcode != 0)
  9598.             return 1 ' 
  9599. insert into dbo.tempcmd(cmdtext) values(@cmd)        
  9600. insert into dbo.tempcmd(cmdtext) values(N'
  9601.     end
  9602. end')
  9603.  
  9604. if (@is_debug = 0)
  9605. begin
  9606.     -- Now we select out the command text pieces in proper order so that our caller,
  9607.     -- xp_execresultset will execute the command that creates the stored procedure.
  9608.     select @dbname = db_name()
  9609.     select @cmd = N'select cmdtext from dbo.tempcmd order by c1'
  9610.     exec @retcode = master..xp_execresultset @cmd, @dbname
  9611.     if (@@error != 0 or @retcode != 0)
  9612.     begin
  9613.         -- roll back the tran
  9614.         rollback tran sp_MSmaketrancftproc
  9615.         return (1)
  9616.     end
  9617.     
  9618.     --
  9619.     -- Check if we create the proc and update sysarticleupdates
  9620.     --
  9621.     select @conflict_proc_id = id from sysobjects where name = @procname and type = 'P '
  9622.     if (@conflict_proc_id is NULL or @conflict_proc_id = 0)
  9623.     begin
  9624.         -- roll back the tran
  9625.         rollback tran sp_MSmaketrancftproc
  9626.         return (1)
  9627.     end
  9628.     else
  9629.     begin
  9630.         update dbo.sysarticleupdates set ins_conflict_proc = @conflict_proc_id
  9631.             where artid = @artid and pubid = @pubid
  9632.         if @@error <> 0
  9633.         begin
  9634.             -- roll back the tran
  9635.             rollback tran sp_MSmaketrancftproc
  9636.             return (1)
  9637.         end
  9638.  
  9639.         -- mark the proc as system object
  9640.         if (@owner in ('dbo','INFORMATION_SCHEMA'))
  9641.         begin
  9642.             exec @retcode = dbo.sp_MS_marksystemobject @procname
  9643.             if (@@error != 0 or @retcode != 0)
  9644.             begin
  9645.                 -- roll back the tran
  9646.                 rollback tran sp_MSmaketrancftproc
  9647.                 return (1)
  9648.             end
  9649.         end
  9650.     end
  9651. end
  9652. else
  9653.     select cmdtext from dbo.tempcmd order by c1
  9654.  
  9655. COMMIT TRAN 
  9656.  
  9657. -- drop the temp tables
  9658. drop table dbo.tempcmd
  9659. drop table #argtab 
  9660. drop table #valtab 
  9661. drop table #paramtab 
  9662. drop table #seltab 
  9663. drop table #sel2tab 
  9664. drop table #decltab 
  9665. drop table #assigntab 
  9666. drop table #where_clausetab 
  9667. drop table #compinstab
  9668. END
  9669. go
  9670.  
  9671. exec dbo.sp_MS_marksystemobject sp_MSmaketrancftproc 
  9672. go
  9673.  
  9674. print ''
  9675. print 'Creating procedure sp_changesubstatus'
  9676. go
  9677. CREATE PROCEDURE sp_changesubstatus (
  9678.     @publication sysname = '%',    /* publication name */
  9679.     @article sysname = '%',        /* article name */
  9680.     @subscriber sysname = '%',      /* subscriber name */
  9681.     @status sysname,                /* subscription status */
  9682.     @previous_status sysname=NULL,  /* previous subscription status */
  9683.     @destination_db sysname = '%',   /* destination database name */
  9684.  
  9685.     @frequency_type int = NULL,
  9686.     @frequency_interval int = NULL,
  9687.     @frequency_relative_interval int = NULL,
  9688.     @frequency_recurrence_factor int = NULL,
  9689.     @frequency_subday int = NULL,
  9690.     @frequency_subday_interval int = NULL,
  9691.     @active_start_time_of_day int = NULL,
  9692.     @active_end_time_of_day int = NULL,
  9693.     @active_start_date int = NULL,
  9694.     @active_end_date int = NULL,
  9695.     @optional_command_line nvarchar(4000) = NULL,
  9696.     @distribution_jobid binary(16) = NULL OUTPUT,
  9697.     @from_auto_sync bit = 0,
  9698.     @ignore_distributor bit = 0,
  9699.     -- Agent offload
  9700.     @offloadagent bit = 0,
  9701.     @offloadserver sysname = NULL,
  9702.     @dts_package_name sysname = NULL,
  9703.     @dts_package_password nvarchar(524) = NULL,
  9704.     @dts_package_location int = 0,
  9705.     @schemastabilityonly int = 0,
  9706.     @distribution_job_name sysname = NULL
  9707.  
  9708. ) AS
  9709.  
  9710.     SET NOCOUNT ON
  9711.     DECLARE @inactive tinyint
  9712.     DECLARE @subscribed tinyint
  9713.     DECLARE @active tinyint
  9714.     DECLARE @initiated tinyint
  9715.     DECLARE @public tinyint
  9716.     DECLARE @replicate_bit smallint
  9717.     DECLARE @msg nvarchar(255)
  9718.     DECLARE @prevstatid tinyint
  9719.     DECLARE @artid int
  9720.     DECLARE @tabid int
  9721.     DECLARE @srvid smallint
  9722.     DECLARE @statusid tinyint
  9723.     DECLARE @distributor sysname
  9724.     DECLARE @distribdb sysname
  9725.     DECLARE @distproc nvarchar (255)
  9726.     DECLARE @pub_db sysname
  9727.     DECLARE @dest_db sysname
  9728.     DECLARE @sub_name sysname
  9729.     DECLARE @sub_status tinyint
  9730.     DECLARE @sub_ts varbinary (16)
  9731.     DECLARE @non_sql_flag bit
  9732.     DECLARE @qcmd nvarchar (4000)
  9733.     DECLARE @cmd1 nvarchar (255)
  9734.     DECLARE @cmd2 nvarchar (255)
  9735.     DECLARE @cmd3 nvarchar (255)
  9736.     DECLARE @retcode int
  9737.     DECLARE @repl_freq tinyint
  9738.     DECLARE @art_type tinyint
  9739.     DECLARE @proccmd  nvarchar(255)
  9740.     DECLARE @procnum  smallint
  9741.     DECLARE @finished_real bit
  9742.     DECLARE @finished_virtual bit
  9743.     DECLARE @virtual_id smallint
  9744.     DECLARE @immediate_sync bit
  9745.     DECLARE @enabled_for_internet bit
  9746.     DECLARE @allow_anonymous bit
  9747.     DECLARE @subscription_type int
  9748.     DECLARE @xact_seqno binary(10)
  9749.     DECLARE @sync_type tinyint
  9750.     DECLARE @automatic tinyint
  9751.     DECLARE @bcp_char tinyint    
  9752.     DECLARE @concurrent_char tinyint    
  9753.  
  9754.     DECLARE @art_change bit
  9755.     declare @login_name sysname
  9756.  
  9757.     DECLARE @pubid int
  9758.     DECLARE @syncinit_lsn binary(10)
  9759.  
  9760.     DECLARE @f_syncstat_posted bit
  9761.  
  9762.     -- synctran
  9763.     DECLARE @update_mode tinyint
  9764.     DECLARE @art_name sysname
  9765.     declare @synctran tinyint
  9766.     declare @no_distproc bit
  9767.     declare @loopback_detection bit
  9768.     
  9769.     /*
  9770.     ** Initializations.
  9771.     */
  9772.     select @synctran = 1
  9773.             
  9774.     SELECT @automatic = 1
  9775.     SELECT @inactive = 0        /* Const: subscription status 'inactive' */
  9776.     SELECT @subscribed = 1      /* Const: subscription status 'subscribed' */
  9777.     SELECT @active = 2          /* Const: subscription status 'active' */
  9778.     SELECT @initiated = 3        /* Const: subscription status 'initiated' */
  9779.     SELECT @public = 0          /* Const: publication status 'public' */
  9780.     SELECT @pub_db = DB_NAME()
  9781.     SELECT @virtual_id = -1
  9782.     SELECT @art_change = 0
  9783.     select @bcp_char = 1
  9784.     select @concurrent_char = 4    
  9785.  
  9786.     SELECT @f_syncstat_posted = 0
  9787.  
  9788.     SELECT @replicate_bit = 2
  9789.  
  9790.     /* 
  9791.     ** Security Check.
  9792.     ** We use login_name stored in syssubscriptions to manage security 
  9793.     */
  9794.  
  9795.     /*
  9796.     ** Parameter Check:  @publication
  9797.     ** Check to make sure that the publication exists, that it's not NULL,
  9798.     ** and that it conforms to the rules for identifiers.
  9799.     */
  9800.  
  9801.     IF @publication IS NULL
  9802.         BEGIN
  9803.             RAISERROR (14043, 16, -1, '@publication')
  9804.             RETURN (1)
  9805.         END
  9806.  
  9807.     IF @publication <> '%'
  9808.         BEGIN
  9809.             EXECUTE @retcode = dbo.sp_validname @publication
  9810.             IF @@ERROR <> 0 OR @retcode <> 0
  9811.             RETURN (1)
  9812.         END
  9813.  
  9814.     IF NOT EXISTS (SELECT * FROM syspublications WHERE name LIKE @publication)
  9815.         BEGIN
  9816.         IF @publication = '%'
  9817.                 RAISERROR (14008, 11, -1)
  9818.         ELSE
  9819.                 RAISERROR (20026, 11, -1, @publication)
  9820.         RETURN (1)
  9821.         END
  9822.  
  9823.     /*
  9824.     ** Parameter Check:  @article
  9825.     ** Check to make sure that the article exists, that it's not null,
  9826.     ** and that it conforms to the rules for identifiers.
  9827.     */
  9828.  
  9829.     IF @article IS NULL
  9830.         BEGIN
  9831.             RAISERROR (14043, 16, -1, '@article')
  9832.             RETURN (1)
  9833.         END
  9834.  
  9835.     /*
  9836.     IF @article <> '%'
  9837.         BEGIN
  9838.             EXECUTE @retcode = dbo.sp_validname @article
  9839.             IF @@ERROR <> 0 OR @retcode <> 0
  9840.             RETURN (1)
  9841.         END
  9842.     */
  9843.  
  9844.     IF NOT EXISTS (SELECT *
  9845.                      FROM sysextendedarticlesview a,
  9846.                           syspublications b
  9847.                 WHERE a.name LIKE @article
  9848.                       AND a.pubid = b.pubid
  9849.                       AND b.name LIKE @publication)
  9850.  
  9851.         BEGIN
  9852.         IF @article = '%'
  9853.                 RAISERROR (14009, 11, -1, @publication)
  9854.         ELSE
  9855.                 RAISERROR (20027, 11, -1, @article)
  9856.         RETURN (1)
  9857.         END
  9858.  
  9859.     /*
  9860.     ** Parameter Check:  @subscriber
  9861.     ** Check to make sure that the subscriber exists, that it is not NULL,
  9862.     ** and that it conforms to the rules for identifiers.
  9863.     ** Null subscriber represents virtual subscriptions
  9864.     */
  9865.  
  9866.     IF @subscriber IS NOT NULL AND @subscriber <> '%'
  9867.     BEGIN    
  9868.         EXECUTE @retcode = dbo.sp_validname @subscriber
  9869.         IF @@ERROR <> 0 OR @retcode <> 0
  9870.         RETURN (1)
  9871.  
  9872.         IF NOT EXISTS (SELECT *
  9873.                          FROM master..sysservers
  9874.                         WHERE UPPER(srvname) = UPPER(@subscriber) collate database_default
  9875.                           AND (srvstatus & 4) <> 0)
  9876.  
  9877.             BEGIN
  9878.                 RAISERROR (14063, 11, -1)
  9879.                 RETURN (1)
  9880.             END
  9881.     END
  9882.  
  9883.     /*
  9884.     ** Parameter Check: @status.
  9885.     ** Set the @statusid according to the @status value.  Values can be
  9886.     ** any of the following:
  9887.     **
  9888.     **      status      statusid
  9889.     **      =========   ========
  9890.     **      inactive           0
  9891.     **      subscribed         1
  9892.     **      active             2
  9893.     **        initiated          3
  9894.     */
  9895.  
  9896.     IF LOWER(@status collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('active', 'subscribed', 'inactive', 'initiated')
  9897.         BEGIN
  9898.             RAISERROR (14065, 16, -1)
  9899.         RETURN (1)
  9900.         END
  9901.  
  9902.     IF LOWER(@status collate SQL_Latin1_General_CP1_CS_AS) IN ('initiated')
  9903.         SELECT @statusid = @initiated
  9904.     ELSE IF LOWER(@status collate SQL_Latin1_General_CP1_CS_AS) IN ('active')
  9905.         SELECT @statusid = @active
  9906.     ELSE IF LOWER(@status collate SQL_Latin1_General_CP1_CS_AS) IN ('subscribed')
  9907.         SELECT @statusid = @subscribed
  9908.     ELSE
  9909.         SELECT @statusid = @inactive
  9910.  
  9911.     /*
  9912.     ** Parameter Check: @previous_status.
  9913.     ** Set the @prevstatid according to the @previous_status value.
  9914.     ** Values can be any of the following:
  9915.     **
  9916.     **      previous_status      prevstatid
  9917.     **      ===============      ==========
  9918.     **      inactive                      0
  9919.     **      subscribed                    1
  9920.     **      active                        2
  9921.     **        initiated                      3
  9922.     */
  9923.  
  9924.     IF @previous_status IS NOT NULL
  9925.     BEGIN
  9926.         IF LOWER(@previous_status collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('initiated','active', 'subscribed', 'inactive')
  9927.         BEGIN
  9928.             RAISERROR (14066, 16, -1)
  9929.             RETURN (1)
  9930.         END
  9931.  
  9932.         IF LOWER(@status collate SQL_Latin1_General_CP1_CS_AS) = LOWER(@previous_status collate SQL_Latin1_General_CP1_CS_AS)
  9933.         BEGIN
  9934.             RAISERROR (14067, 16, -1)
  9935.             RETURN (1)
  9936.         END
  9937.  
  9938.         IF LOWER(@previous_status collate SQL_Latin1_General_CP1_CS_AS) IN ('initiated')
  9939.             SELECT @prevstatid = @initiated
  9940.         ELSE IF LOWER(@previous_status collate SQL_Latin1_General_CP1_CS_AS) IN ('active')
  9941.             SELECT @prevstatid = @active
  9942.         ELSE IF LOWER(@previous_status collate SQL_Latin1_General_CP1_CS_AS) IN ('subscribed')
  9943.             SELECT @prevstatid = @subscribed
  9944.         ELSE
  9945.            SELECT @prevstatid = @inactive
  9946.     END
  9947.  
  9948.     /*
  9949.     ** Parameter Check: @destination_db.
  9950.     ** Set @destination_db to current database if not specified.  Make
  9951.     ** sure that the @destination_db conforms to the rules for identifiers.
  9952.     */
  9953.  
  9954.     IF @destination_db <> '%' 
  9955.     BEGIN
  9956.         EXECUTE @retcode = dbo.sp_validname @destination_db
  9957.         IF @retcode <> 0
  9958.         RETURN (1)
  9959.     END
  9960.  
  9961.     /*
  9962.     ** Get distribution server information for remote RPC
  9963.     ** subscription calls.
  9964.     ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
  9965.     */
  9966.     if @ignore_distributor = 1 
  9967.         select @no_distproc = 1
  9968.     else
  9969.         select @no_distproc = 0
  9970.  
  9971.     IF @no_distproc = 0 --and @from_auto_sync = 0 
  9972.     BEGIN
  9973.         EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  9974.                                            @distribdb = @distribdb OUTPUT
  9975.  
  9976.         IF @@ERROR <> 0
  9977.         BEGIN
  9978.             RAISERROR (14071, 16, -1)
  9979.             RETURN (1)
  9980.         END
  9981.  
  9982.         IF @retcode <> 0 OR @distribdb IS NULL OR @distributor IS NULL
  9983.         BEGIN
  9984.             RAISERROR (14071, 16, -1)
  9985.             RETURN (1)
  9986.         END
  9987.     END
  9988.  
  9989.  
  9990.     create table #sysextendedarticlesview
  9991.     (
  9992.     artid               int                 NULL,
  9993.     columns             varbinary(32)       NULL,
  9994.     creation_script     nvarchar(255)       collate database_default null,
  9995.     del_cmd             nvarchar(255)       collate database_default null,
  9996.     description         nvarchar(255)       collate database_default null,
  9997.     dest_table          sysname             collate database_default null,
  9998.     filter              int                 NULL,
  9999.     filter_clause       ntext               NULL,
  10000.     ins_cmd             nvarchar(255)       collate database_default null,
  10001.     name                sysname             collate database_default null,
  10002.     objid               int                 NULL,
  10003.     pubid               int                 NULL,
  10004.     pre_creation_cmd    tinyint             NULL,
  10005.     status              tinyint             NULL,
  10006.     sync_objid          int                 NULL,
  10007.     type                tinyint             NULL,
  10008.     upd_cmd             nvarchar(255)       collate database_default null,
  10009.     schema_option       binary(8)           NULL,
  10010.     dest_owner          sysname             collate database_default null
  10011.     )
  10012.  
  10013.     insert into #sysextendedarticlesview select * from sysextendedarticlesview
  10014.  
  10015.     begin tran
  10016.     save TRANSACTION changesubstatus
  10017.  
  10018.         SELECT @finished_virtual = 0
  10019.         SELECT @finished_real = 0
  10020.  
  10021.         /* 
  10022.         ** If @subscriber is null, don't process real subscriptions
  10023.         ** If @subscriber is not null and '%', don't process virtual subscriptions
  10024.         */
  10025.         IF @subscriber IS NULL SELECT @finished_real = 1
  10026.         ELSE IF @subscriber <> '%'  SELECT @finished_virtual = 1
  10027.  
  10028.         WHILE (@finished_real = 0 OR @finished_virtual = 0)
  10029.         BEGIN
  10030.             /*
  10031.             ** Declare cursor containing subscriptions to be updated.
  10032.             */
  10033.             IF @finished_real = 0
  10034.             BEGIN
  10035.                 IF @previous_status IS NOT NULL
  10036.                 BEGIN
  10037.                     DECLARE hCsubstatus CURSOR LOCAL SCROLL_LOCKS FOR
  10038.                         SELECT sub.artid,
  10039.                                art.objid,
  10040.                                sub.srvid,
  10041.                                ss.srvname,
  10042.                                sub.dest_db,
  10043.                                sub.status,
  10044.                            case when ss.srvproduct = 'MSREPL-NONSQL' or
  10045.                                 pub.allow_dts = 1
  10046.                                 then 1
  10047.                            else 0 end,
  10048.                            pub.repl_freq,
  10049.                                art.type,
  10050.                            pub.immediate_sync,
  10051.                            pub.enabled_for_internet,
  10052.                            pub.allow_anonymous,
  10053.                            sub.subscription_type,
  10054.                            sub.sync_type,
  10055.                            sub.update_mode,
  10056.                            art.name,
  10057.                            sub.login_name,
  10058.                            sub.loopback_detection,
  10059.                            pub.pubid
  10060.                           FROM syssubscriptions sub,
  10061.                                #sysextendedarticlesview art,
  10062.                                syspublications pub,
  10063.                                master..sysservers ss
  10064.                          WHERE pub.name LIKE @publication collate database_default
  10065.                            AND art.name LIKE @article collate database_default
  10066.                            AND ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber) collate database_default))
  10067.                            AND sub.srvid = ss.srvid
  10068.                            AND sub.artid = art.artid
  10069.                            AND art.pubid = pub.pubid
  10070.                            AND sub.status = @prevstatid
  10071.                            AND ((@destination_db = N'%') OR (sub.dest_db = @destination_db collate database_default))
  10072.                 END
  10073.                 ELSE
  10074.                 BEGIN
  10075.                     DECLARE hCsubstatus CURSOR LOCAL SCROLL_LOCKS FOR
  10076.                         SELECT sub.artid,
  10077.                                art.objid,
  10078.                                sub.srvid,
  10079.                                ss.srvname,
  10080.                                sub.dest_db,
  10081.                                sub.status,
  10082.                            case when ss.srvproduct = 'MSREPL-NONSQL' or
  10083.                                 pub.allow_dts = 1
  10084.                                 then 1
  10085.                            else 0 end,
  10086.                            pub.repl_freq,
  10087.                                art.type,
  10088.                            pub.immediate_sync,
  10089.                            pub.enabled_for_internet,
  10090.                            pub.allow_anonymous,
  10091.                            sub.subscription_type,
  10092.                            sub.sync_type,
  10093.                            sub.update_mode,
  10094.                            art.name,
  10095.                            sub.login_name,
  10096.                            sub.loopback_detection,
  10097.                            pub.pubid
  10098.                           FROM syssubscriptions sub,
  10099.                                #sysextendedarticlesview art,
  10100.                                syspublications pub,
  10101.                                master..sysservers ss
  10102.                          WHERE pub.name LIKE @publication collate database_default
  10103.                            AND art.name LIKE @article collate database_default
  10104.                            AND ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber) collate database_default))
  10105.                            AND sub.srvid = ss.srvid
  10106.                            AND sub.artid = art.artid
  10107.                            AND art.pubid = pub.pubid
  10108.                            AND ((@destination_db = N'%') OR (sub.dest_db = @destination_db))
  10109.                 END           
  10110.                 SELECT @finished_real = 1
  10111.             END
  10112.  
  10113.             ELSE IF @finished_virtual = 0  
  10114.             BEGIN
  10115.                 DECLARE @sub_bit smallint
  10116.                 DECLARE @null_name sysname
  10117.  
  10118.                 SELECT @sub_bit = 4
  10119.                 SELECT @null_name = NULL
  10120.  
  10121.                 /*
  10122.                 ** Treat anonymous virtual subscription as DSN subscriber.
  10123.                 ** This will cause sp_MSarticlecol being called in sp_changesubstatus
  10124.                 */
  10125.                 DECLARE hCsubstatus CURSOR LOCAL SCROLL_LOCKS FOR
  10126.                     SELECT sub.artid,
  10127.                            art.objid,
  10128.                            sub.srvid,
  10129.                            @null_name,              /* subscriber name. NULL for virtual */
  10130.                            sub.dest_db,
  10131.                            sub.status,
  10132.                       case when (pub.allow_anonymous = 1 and (pub.sync_method = @bcp_char or pub.sync_method = @concurrent_char)) or
  10133.                             pub.allow_dts = 1 then 1
  10134.                        else 0 end, /*indicate dsn or not */ 
  10135.                        pub.repl_freq,
  10136.                        art.type,
  10137.                        pub.immediate_sync,
  10138.                        pub.enabled_for_internet,
  10139.                        pub.allow_anonymous,
  10140.                        sub.subscription_type,
  10141.                        sub.sync_type,
  10142.                        sub.update_mode,
  10143.                        art.name,
  10144.                        login_name,
  10145.                        sub.loopback_detection,
  10146.                        pub.pubid
  10147.  
  10148.                       FROM syssubscriptions sub,
  10149.                            #sysextendedarticlesview art,
  10150.                            syspublications pub
  10151.                      WHERE pub.name LIKE @publication
  10152.                        AND art.name LIKE @article
  10153.                        AND sub.srvid = -1
  10154.                        AND sub.artid = art.artid
  10155.                        AND art.pubid = pub.pubid
  10156.                 SELECT @finished_virtual = 1
  10157.             END
  10158.  
  10159.             OPEN hCsubstatus
  10160.             FETCH hCsubstatus INTO @artid, @tabid, @srvid, @sub_name, @dest_db,
  10161.                 @sub_status, @non_sql_flag, @repl_freq, @art_type,
  10162.                 @immediate_sync, @enabled_for_internet,
  10163.                 @allow_anonymous, @subscription_type, @sync_type, @update_mode,
  10164.                 @art_name, @login_name, @loopback_detection,@pubid
  10165.  
  10166.  
  10167.             WHILE (@@fetch_status <> -1)
  10168.             BEGIN
  10169.  
  10170.                 IF  suser_sname(suser_sid()) <> @login_name AND is_srvrolemember('sysadmin') <> 1  
  10171.                     AND is_member ('db_owner') <> 1
  10172.                 BEGIN
  10173.                         RAISERROR (14126, 11, -1)
  10174.                         RETURN (1)
  10175.                 END
  10176.                 /*
  10177.                 ** condition 1:
  10178.                 ** If current status is same as new status, and status is not 'initiated' do nothing.
  10179.                 ** If both old and new status = 'initiated', this indicates that the 
  10180.                 ** snapshot agent previously bombed out between the initiation and activation stages and
  10181.                 ** is now again trying to sync the publication.
  10182.                 **
  10183.                 ** condition 2:
  10184.                 ** @auto_sync_only is used by snapshot for immediate_sync
  10185.                 ** publications.
  10186.                 **
  10187.                 ** condition 3:
  10188.                 ** Because sp_MSactivate_auto_sub (and thus the snapshot agent)
  10189.                 ** calls this procedure for all subscriptions, we need to ignore
  10190.                 ** the real subscriptions that are already active so that they won't be
  10191.                 ** transitioned to the initiated state.  If we don't do this, those
  10192.                 ** subscriptions will be resynced using the new snapshot.
  10193.                 ** 
  10194.                 ** however, we DO want a new snapshot to be generated for virtual
  10195.                 ** subscriptions to active publications.
  10196.                 **
  10197.                 */
  10198.                 IF  (@sub_status = @statusid AND @sub_status <> @initiated ) OR
  10199.                     (@from_auto_sync = 1 AND @sync_type <> @automatic) OR
  10200.                     (@sub_status = @active AND @statusid = @initiated AND @srvid <> -1 AND @from_auto_sync = 1)
  10201.                 BEGIN
  10202.                     FETCH hCsubstatus INTO @artid, @tabid, @srvid, @sub_name,
  10203.                        @dest_db, @sub_status, @non_sql_flag, @repl_freq, @art_type, 
  10204.                        @immediate_sync, @enabled_for_internet,
  10205.                        @allow_anonymous, @subscription_type, @sync_type, @update_mode,
  10206.                        @art_name, @login_name, @loopback_detection, @pubid
  10207.  
  10208.                     CONTINUE
  10209.                 END
  10210.  
  10211.                 -- If changing a virtual subscription to 'subscribed' status
  10212.                 -- change the immediate_sync_ready bit
  10213.                 if @statusid = @subscribed and @sub_name is NULL
  10214.                 begin
  10215.                     UPDATE syspublications SET immediate_sync_ready = 0 WHERE 
  10216.                         pubid = @pubid and
  10217.                         immediate_sync_ready <> 0
  10218.                     IF @@ERROR <> 0
  10219.                     BEGIN
  10220.                       CLOSE hCsubstatus
  10221.                       DEALLOCATE hCsubstatus
  10222.                       if @@trancount > 0
  10223.                         begin
  10224.                             ROLLBACK TRANSACTION changesubstatus
  10225.                             commit tran
  10226.                         end
  10227.                       RETURN (1)
  10228.                     END
  10229.                 end
  10230.  
  10231.  
  10232.                 -- acquire schema lock, mark rollback point in order to allow
  10233.                 -- for 'unflush' of proc cache
  10234.  
  10235.                 declare @qualified_name nvarchar(512)
  10236.  
  10237.                 exec dbo.sp_MSget_qualified_name @tabid, @qualified_name output
  10238.                 exec dbo.sp_replupdateschema @qualified_name, @schemastabilityonly
  10239.  
  10240.                 /*
  10241.                 ** Update syssubscription status
  10242.                 */
  10243.                 UPDATE syssubscriptions
  10244.                        SET status = @statusid
  10245.                        FROM syssubscriptions sub,
  10246.                            sysextendedarticlesview art,
  10247.                            syspublications pub
  10248.                        WHERE pub.name LIKE @publication
  10249.                             AND art.artid = @artid
  10250.                             AND sub.srvid = @srvid
  10251.                             AND sub.artid = @artid
  10252.                             AND art.pubid = pub.pubid
  10253.                             AND sub.dest_db = @dest_db
  10254.                 if @@ERROR <> 0
  10255.                                BEGIN
  10256.                                CLOSE hCsubstatus
  10257.                                DEALLOCATE hCsubstatus
  10258.                                 if @@trancount > 0
  10259.                                 begin
  10260.                                     ROLLBACK TRANSACTION changesubstatus
  10261.                                     commit tran
  10262.                                 end
  10263.                                 RAISERROR (14053, 16, -1)
  10264.                                    RETURN (1)
  10265.                                END
  10266.  
  10267.                 --
  10268.                 -- Subscription reinitialization processing for Immediate 
  10269.                 -- and Queued publications
  10270.                 --
  10271.                 if (@update_mode in (1,2,3,4,5))
  10272.                 begin
  10273.                     select @retcode = 0
  10274.                     IF ((@statusid != @active) AND (@sub_status = @active))
  10275.                     begin
  10276.                         --
  10277.                         -- If we are going from active state to subscribed
  10278.                         -- set the reinit column so that no more updates from
  10279.                         -- subscriber are applied until (re)activation
  10280.                         --
  10281.                         update dbo.syssubscriptions
  10282.                         set queued_reinit = 1
  10283.                         where 
  10284.                             artid = @artid 
  10285.                             and srvid = @srvid
  10286.                             and dest_db = @dest_db
  10287.                     end
  10288.                     ELSE IF ((@statusid = @active) AND (@sub_status != @active ))
  10289.                     begin
  10290.                         --
  10291.                         -- If we are going from subscribed state to active state
  10292.                         --
  10293.                         if (@update_mode = 1)
  10294.                         begin
  10295.                             --
  10296.                             -- Sync tran case : reset the reinit column
  10297.                             --
  10298.                             update dbo.syssubscriptions
  10299.                             set queued_reinit = 0
  10300.                             where 
  10301.                                 artid = @artid 
  10302.                                 and srvid = @srvid
  10303.                                 and dest_db = @dest_db
  10304.                         end
  10305.  
  10306.                         --
  10307.                         -- For queued case : we do not need to send compensating
  10308.                         -- command anymore, sp_addqueued_artinfo will do the 
  10309.                         -- queue reinitialization for all types of queued
  10310.                         -- subscriptions
  10311.                         --
  10312.  
  10313.                         /**********
  10314.                         else
  10315.                         begin
  10316.                             -- 
  10317.                             -- Queued case : send a compensating action command to 
  10318.                             -- subscriber to reinitialize its queue
  10319.                             --
  10320.                             select @qcmd = N'exec sp_MSreset_queue ''' + @@servername + '''' + 
  10321.                                 ', ''' + db_name() + '''' +
  10322.                                 ', ''' + name + '''' +
  10323.                                 ', ' + cast(@artid as nvarchar(8))
  10324.                             from syspublications
  10325.                             where pubid = @pubid
  10326.                                                       
  10327.                             exec @retcode = dbo.sp_MSadd_compensating_cmd
  10328.                                 @orig_srv = @sub_name
  10329.                                 ,@orig_db = @dest_db
  10330.                                 ,@command = @qcmd
  10331.                                 ,@article_id = @artid 
  10332.                                 ,@publication_id = @pubid
  10333.                         end
  10334.                         **********/
  10335.                     end                    
  10336.  
  10337.                     --
  10338.                     -- Check for error
  10339.                     --
  10340.                     if (@@error != 0 or @retcode != 0)
  10341.                     begin
  10342.                         CLOSE hCsubstatus
  10343.                         DEALLOCATE hCsubstatus
  10344.                         if @@trancount > 0
  10345.                         begin
  10346.                             ROLLBACK TRANSACTION changesubstatus
  10347.                             commit tran
  10348.                         end
  10349.                         RAISERROR (14053, 16, -1)
  10350.                         RETURN (1)
  10351.                     end
  10352.                 end
  10353.  
  10354.                 /*
  10355.                 ** Get timestamp of subscription.
  10356.                 */
  10357.                 EXEC @retcode = dbo.sp_replincrementlsn @xact_seqno OUTPUT
  10358.                 IF @@ERROR <> 0 or @retcode <> 0
  10359.                             BEGIN
  10360.                                CLOSE hCsubstatus
  10361.                                DEALLOCATE hCsubstatus
  10362.                                if @@trancount > 0
  10363.                                 begin
  10364.                                     ROLLBACK TRANSACTION changesubstatus
  10365.                                     commit tran
  10366.                                 end
  10367.                                RETURN (1)
  10368.                             END
  10369.                 select @sub_ts = @xact_seqno
  10370.  
  10371.  
  10372.                 IF @sub_ts IS NULL
  10373.                             BEGIN
  10374.                                CLOSE hCsubstatus
  10375.                                DEALLOCATE hCsubstatus
  10376.                                if @@trancount > 0
  10377.                                 begin
  10378.                                     ROLLBACK TRANSACTION changesubstatus
  10379.                                     commit tran
  10380.                                 end
  10381.                                 RAISERROR (14053, 16, -1)
  10382.                                RETURN (1)
  10383.                             END
  10384.                 
  10385.                 -------------------------------------------------------------------
  10386.                 -- If initiating the subscription, toss a SYNCINIT token into the 
  10387.                 -- log for the article and return LSN as a results set
  10388.                 --
  10389.                 -- Note:  This should come after the subscription LSN is obtained.
  10390.                 -- in order to assure proper application of SYNSTAT tokens in the
  10391.                 -- distribution database
  10392.                 -------------------------------------------------------------------
  10393.  
  10394.                 IF @statusid = @initiated --and @sub_status <> @initiated
  10395.                 BEGIN
  10396.                     -- set filtered status.  Must log old text information during initiated state
  10397.                     -- in order to support update splitting
  10398.  
  10399.                     exec sp_MSsetfilteredstatus @tabid
  10400.  
  10401.                     -- set nonsqlsub status.  must prevent UPDATETEXT operations during
  10402.                     -- initiated state
  10403.  
  10404.                     exec sp_MSarticlecol @artid, NULL,N'nonsqlsub', N'add'
  10405.                     exec sp_replpostsyncstatus @pubid, @artid, 1, @syncinit_lsn output
  10406.                     if @f_syncstat_posted = 0
  10407.                     begin
  10408.                         select @pubid, @artid, @syncinit_lsn
  10409.                         select @f_syncstat_posted = 1
  10410.                     end
  10411.                 END
  10412.  
  10413.                 -------------------------------------------------------------------
  10414.                 -- If changing the state FROM initiated, post a SYNCDONE token to the 
  10415.                 -- log for the article. 
  10416.                 -------------------------------------------------------------------
  10417.                 IF @sub_status = @initiated and @statusid <> @initiated
  10418.                 BEGIN
  10419.                     -- reset filtered status to normal value
  10420.  
  10421.                     exec sp_MSsetfilteredstatus @tabid
  10422.  
  10423.                     -- clear nonsqlsub status for this article.
  10424.  
  10425.                     exec sp_MSarticlecol @artid, NULL,N'nonsqlsub', N'drop'
  10426.  
  10427.                     --if @f_syncstat_posted = 0
  10428.                     --begin
  10429.                         exec sp_replpostsyncstatus @pubid, @artid, 0, @syncinit_lsn output
  10430.                     --    select @f_syncstat_posted = 1
  10431.                     --end
  10432.                 END
  10433.  
  10434.                 /*
  10435.                 ** If activating subscription, update sysextendedarticlesview, sysobjects and
  10436.                 ** MSrepl_subscriptions.
  10437.                 */
  10438.                 IF @statusid in ( @active, @initiated )
  10439.                 BEGIN
  10440.                     
  10441.                     /*
  10442.                     ** Update status of article to show it has been activated.
  10443.                     */
  10444.                     IF @repl_freq = 0 and EXISTS (SELECT * FROM sysextendedarticlesview WHERE artid = @artid
  10445.                         AND status & 1 <> 1)
  10446.                     BEGIN
  10447.                         -- At most one row will be updated in the following two updates as the artid is unique
  10448.                         -- among both sysarticles and sysschemaarticles
  10449.                         UPDATE sysarticles SET status = status | 1 WHERE artid = @artid
  10450.                         IF @@ERROR <> 0
  10451.                             BEGIN
  10452.                                 CLOSE hCsubstatus
  10453.                                 DEALLOCATE hCsubstatus
  10454.                                 if @@trancount > 0
  10455.                                 begin
  10456.                                     ROLLBACK TRANSACTION changesubstatus
  10457.                                     commit tran
  10458.                                 end
  10459.                                 RAISERROR (14069, 16, -1)
  10460.                                 RETURN (1)
  10461.                             END
  10462.                         UPDATE sysschemaarticles SET status = status | 1 WHERE artid = @artid
  10463.                         IF @@ERROR <> 0
  10464.                             BEGIN
  10465.                                 CLOSE hCsubstatus
  10466.                                 DEALLOCATE hCsubstatus
  10467.                                 if @@trancount > 0
  10468.                                 begin
  10469.                                     ROLLBACK TRANSACTION changesubstatus
  10470.                                     commit tran
  10471.                                 end
  10472.                                 RAISERROR (14069, 16, -1)
  10473.                                 RETURN (1)
  10474.                             END
  10475.                         SELECT @art_change = 1
  10476.                     END
  10477.  
  10478.                         /*
  10479.                         ** Turn the replication flag on for this object in the
  10480.                         ** sysobjects table (make it logbased).
  10481.                         */
  10482.  
  10483.                     if @repl_freq = 0
  10484.                       BEGIN
  10485.                         UPDATE sysobjects SET replinfo = replinfo | @replicate_bit
  10486.                         WHERE id = ( SELECT objid FROM sysextendedarticlesview WHERE artid = @artid )
  10487.                       END
  10488.  
  10489.                       IF @@ERROR <> 0
  10490.                       BEGIN
  10491.                           CLOSE hCsubstatus
  10492.                           DEALLOCATE hCsubstatus
  10493.                           if @@trancount > 0
  10494.                             begin
  10495.                                 ROLLBACK TRANSACTION changesubstatus
  10496.                                 commit tran
  10497.                             end
  10498.                           RAISERROR (14068, 16, -1)
  10499.                           RETURN (1)
  10500.                       END
  10501.  
  10502.                 END
  10503.  
  10504.                 /*
  10505.                 ** Update status of all columns if subscriber is non-SQL Server.
  10506.                 */
  10507.                 IF @non_sql_flag <> 0 AND ( @art_type & 1 ) = 1
  10508.                 BEGIN
  10509.                     IF @statusid = @subscribed OR @statusid = @active
  10510.                     BEGIN
  10511.  
  10512.                         EXEC @retcode = dbo.sp_MSarticlecol @artid, NULL,
  10513.                                                           'nonsqlsub', 'add'
  10514.                         IF @@ERROR <> 0 OR @retcode <> 0
  10515.                         BEGIN
  10516.                             CLOSE hCsubstatus
  10517.                             DEALLOCATE hCsubstatus
  10518.                             if @@trancount > 0
  10519.                             begin
  10520.                                 ROLLBACK TRANSACTION changesubstatus
  10521.                                 commit tran
  10522.                             end
  10523.                             RAISERROR (14068, 16, -1)
  10524.                             RETURN (1)
  10525.                         END
  10526.  
  10527.  
  10528.                     END
  10529.                     ELSE IF @statusid = @inactive
  10530.                     BEGIN
  10531.  
  10532.                         EXEC @retcode = dbo.sp_MSarticlecol @artid, NULL,
  10533.                                                           'nonsqlsub', 'drop'
  10534.                         IF @@ERROR <> 0 OR @retcode <> 0
  10535.                         BEGIN
  10536.                           CLOSE hCsubstatus
  10537.                           DEALLOCATE hCsubstatus
  10538.                           if @@trancount > 0
  10539.                             begin
  10540.                                 ROLLBACK TRANSACTION changesubstatus
  10541.                                 commit tran
  10542.                             end
  10543.                           RAISERROR (14068, 16, -1)
  10544.                           RETURN (1)
  10545.                         END
  10546.                     END
  10547.                 END
  10548.  
  10549.                 
  10550.                 /*
  10551.                 ** If deactivating subscription, update sysextendedarticlesview, sysobjects and
  10552.                 ** MSrepl_subscriptions.
  10553.                 */
  10554.  
  10555.                 IF @statusid NOT IN( @active, @initiated ) AND @sub_status IN ( @active, @initiated )
  10556.                 BEGIN
  10557.                     /*
  10558.                     ** Set the article status to 'inactive' if there are
  10559.                     ** no other active subscriptions on it.
  10560.                     */
  10561.                     IF NOT EXISTS (SELECT * FROM syssubscriptions WHERE
  10562.                        artid = @artid AND status = @active)
  10563.                     BEGIN
  10564.                         IF EXISTS (SELECT * FROM sysextendedarticlesview WHERE artid = @artid
  10565.                             AND status & 1 = 1)
  10566.                         BEGIN
  10567.                             -- At most one row will be updated in the following two updates as the artid is unique
  10568.                             -- among both sysarticles and sysschemaarticles
  10569.                             UPDATE sysarticles SET status = status & ~1 WHERE
  10570.                                 artid = @artid
  10571.                             IF @@ERROR <> 0
  10572.                             BEGIN
  10573.                                 CLOSE hCsubstatus
  10574.                                 DEALLOCATE hCsubstatus
  10575.                                 if @@trancount > 0
  10576.                                 begin
  10577.                                     ROLLBACK TRANSACTION changesubstatus
  10578.                                     commit tran
  10579.                                 end
  10580.                                 RAISERROR (14069, 16, -1)
  10581.                                 RETURN (1)
  10582.                             END
  10583.                             UPDATE sysschemaarticles SET status = status & ~1 WHERE
  10584.                                 artid = @artid
  10585.                             IF @@ERROR <> 0
  10586.                             BEGIN
  10587.                                 CLOSE hCsubstatus
  10588.                                 DEALLOCATE hCsubstatus
  10589.                                 if @@trancount > 0
  10590.                                 begin
  10591.                                     ROLLBACK TRANSACTION changesubstatus
  10592.                                     commit tran
  10593.                                 end
  10594.                                 RAISERROR (14069, 16, -1)
  10595.                                 RETURN (1)
  10596.                             END
  10597.  
  10598.                             SELECT @art_change = 1
  10599.                         END
  10600.                     END
  10601.  
  10602.                     /*
  10603.                     ** Set the object replication bits  to 'inactive' if
  10604.                     ** there are no other active subscriptions on the
  10605.                     ** table.
  10606.                     */
  10607.                     IF NOT EXISTS (SELECT * FROM syssubscriptions WHERE
  10608.                         artid IN (SELECT sa.artid FROM sysextendedarticlesview sa, syspublications sp WHERE
  10609.                         sa.objid = @tabid and sa.pubid = sp.pubid and sp.repl_freq = 0) AND status = @active)
  10610.                     BEGIN
  10611.                         UPDATE sysobjects SET replinfo =  replinfo & ~@replicate_bit
  10612.                         WHERE id = (SELECT objid FROM sysextendedarticlesview WHERE artid = @artid )
  10613.  
  10614.                         IF @@ERROR <> 0
  10615.                         BEGIN
  10616.                            CLOSE hCsubstatus
  10617.                             DEALLOCATE hCsubstatus
  10618.                             RAISERROR (14068, 16, -1)
  10619.                             if @@trancount > 0
  10620.                             begin
  10621.                                 ROLLBACK TRANSACTION changesubstatus
  10622.                                 commit tran
  10623.                             end
  10624.                             RETURN (1)
  10625.                         END
  10626.                     END
  10627.                 END
  10628.  
  10629.                 -- Note:  Not only do we need to have the replupdateschema already executed
  10630.                 -- so we can handle rollbacks, we also need to
  10631.                 -- acquire the schema lock before RPC to the distributor to avoid livelock
  10632.                 -- with snapshot agents. Snapshot agents acquire lock on user table before
  10633.                 -- updating the distribution db.
  10634.  
  10635.                 if @no_distproc = 0
  10636.                 begin
  10637.                     /*
  10638.                     ** Add the active subscription to the distributor's
  10639.                     ** subscriptions table if changing status from @inactive
  10640.                     */
  10641.                     IF @sub_status = @inactive 
  10642.                     -- From inactive to subscribed or active
  10643.                     BEGIN
  10644.  
  10645.                         DECLARE @null_char sysname
  10646.                         SELECT @null_char = NULL
  10647.  
  10648.                         DECLARE @zero_bit bit
  10649.                         SELECT @zero_bit = 0
  10650.  
  10651.                         SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSadd_subscription'
  10652.                         EXEC @retcode = @distproc @@SERVERNAME, @pub_db, @sub_name, 
  10653.                             @artid, @dest_db, @statusid, @sub_ts,
  10654.                             @publication, 
  10655.                             @null_char, /* Pass null to @article, we already gave @artid */
  10656.                             @subscription_type,
  10657.                             --@immediate_sync, 
  10658.                             @sync_type, 
  10659.                             @zero_bit,
  10660.                             @frequency_type,
  10661.                             @frequency_interval,
  10662.                             @frequency_relative_interval,
  10663.                             @frequency_recurrence_factor,
  10664.                             @frequency_subday,
  10665.                             @frequency_subday_interval,
  10666.                             @active_start_time_of_day,
  10667.                             @active_end_time_of_day,
  10668.                             @active_start_date,
  10669.                             @active_end_date,
  10670.                             @optional_command_line = @optional_command_line,
  10671.                             -- synctran
  10672.                             @update_mode = @update_mode,
  10673.                             @loopback_detection = @loopback_detection,
  10674.                             @distribution_jobid = @distribution_jobid OUTPUT,
  10675.                             @offloadagent = @offloadagent,
  10676.                             @offloadserver = @offloadserver,
  10677.                             @dts_package_name = @dts_package_name,
  10678.                             @dts_package_password = @dts_package_password,
  10679.                             @dts_package_location = @dts_package_location,
  10680.                             @distribution_job_name = @distribution_job_name
  10681.  
  10682.                         IF @@ERROR <> 0 OR @retcode <> 0
  10683.                         BEGIN
  10684.                             CLOSE hCsubstatus
  10685.                             DEALLOCATE hCsubstatus
  10686.                             RAISERROR (14070, 16, -1)
  10687.                             if @@trancount > 0
  10688.                             begin
  10689.                                 ROLLBACK TRANSACTION changesubstatus
  10690.                                 commit tran
  10691.                             end
  10692.                             RETURN (1)
  10693.                         END
  10694.                     END
  10695.                     ELSE
  10696.                     -- From subscribed or active to others
  10697.                     BEGIN
  10698.                         /*
  10699.                         ** Drop the deactivated subscription from the distributor's
  10700.                         ** subscriptions table.
  10701.                         */
  10702.                         IF @statusid = @inactive
  10703.                         -- From subscribed to inactive or from active to inactive
  10704.                         BEGIN
  10705.                             SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSdrop_subscription'
  10706.                             EXEC @retcode = @distproc @@SERVERNAME, @pub_db, @sub_name,  @artid, @dest_db, @publication
  10707.                             IF @@ERROR <> 0 OR @retcode <> 0
  10708.                             BEGIN
  10709.                                 CLOSE hCsubstatus
  10710.                                 DEALLOCATE hCsubstatus
  10711.                                 RAISERROR (14070, 16, -1)
  10712.                                 if @@trancount > 0
  10713.                                 begin
  10714.                                     ROLLBACK TRANSACTION changesubstatus
  10715.                                     commit tran
  10716.                                 end
  10717.                                 RETURN (1)
  10718.                             END
  10719.                         END
  10720.                         ELSE 
  10721.                         -- From subscribed to initiated to active or from active to subscribed.
  10722.                         BEGIN
  10723.                             -- Don't do it if activating the subscription for snapshot agent.
  10724.                             --IF NOT (@from_auto_sync = 1 AND @statusid in(@active, @initiated) )
  10725.                             IF NOT (@from_auto_sync = 1 AND @statusid in(@active) )
  10726.                             BEGIN
  10727.                                 SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSupdate_subscription'
  10728.                                 EXEC @retcode = @distproc @@SERVERNAME, @pub_db, @sub_name, @artid, @statusid, @sub_ts, @dest_db
  10729.                                 IF @@ERROR <> 0 OR @retcode <> 0
  10730.                                 BEGIN
  10731.                                     CLOSE hCsubstatus
  10732.                                     DEALLOCATE hCsubstatus
  10733.                                     RAISERROR (14070, 16, -1)
  10734.                                     if @@trancount > 0
  10735.                                     begin
  10736.                                         ROLLBACK TRANSACTION changesubstatus
  10737.                                         commit tran
  10738.                                     end
  10739.                                     RETURN (1)
  10740.                                 END
  10741.                             END
  10742.                         END
  10743.                     END
  10744.                 end
  10745.  
  10746.                 /*
  10747.                 ** Set internal object replication bit  to 'inactive' if
  10748.                 ** there are no other active subscriptions on the
  10749.                 ** table.
  10750.                 */
  10751.  
  10752.                 IF @statusid = @inactive AND @sub_status IN (@active,@initiated) AND
  10753.                     NOT EXISTS (SELECT * FROM syssubscriptions WHERE
  10754.                     artid IN (SELECT artid FROM sysextendedarticlesview WHERE
  10755.                     objid = @tabid) AND status IN (@active,@initiated) )
  10756.                 BEGIN
  10757.                        /*
  10758.                        ** If it's a procedure execution article, clear proc status bits
  10759.                        */
  10760.                        IF (@art_type & 8 ) = 8
  10761.                        BEGIN
  10762.                            UPDATE sysobjects SET replinfo = replinfo & ~24 WHERE id = @tabid
  10763.                        END
  10764.                 END
  10765.  
  10766.  
  10767.                 /* Turn on object replication */
  10768.  
  10769.                 ELSE IF @statusid = @active
  10770.                 BEGIN
  10771.                        IF (@art_type & 24 ) = 24
  10772.                        BEGIN
  10773.  
  10774.                            UPDATE sysobjects SET replinfo = replinfo | 24 WHERE id = @tabid
  10775.                        END
  10776.                        ELSE IF( @art_type & 8 ) = 8
  10777.                        BEGIN
  10778.                            UPDATE sysobjects SET replinfo = replinfo | 8 WHERE id = @tabid
  10779.                        END
  10780.                 END
  10781.  
  10782.  
  10783.                 exec dbo.sp_MSget_qualified_name @tabid, @qualified_name output
  10784.                 exec dbo.sp_replupdateschema @qualified_name, @schemastabilityonly
  10785.  
  10786.                /*
  10787.                ** Get next row.
  10788.                */
  10789.                FETCH hCsubstatus INTO @artid, @tabid, @srvid, @sub_name, @dest_db,
  10790.                @sub_status, @non_sql_flag, @repl_freq, @art_type ,  
  10791.                @immediate_sync, @enabled_for_internet,
  10792.                @allow_anonymous, @subscription_type, @sync_type, @update_mode,
  10793.                 @art_name, @login_name, @loopback_detection, @pubid
  10794.  
  10795.           
  10796.                                     
  10797.            END  -- end while for cursor
  10798.  
  10799.            CLOSE hCsubstatus
  10800.            DEALLOCATE hCsubstatus
  10801.         
  10802.         END -- end while for virtual and real
  10803.  
  10804.         -- force refresh of article cache
  10805.         -- Only do it if necessary
  10806.         -- No need on brute force cleanup
  10807.         IF ( @art_change = 1 ) and ( @ignore_distributor = 0 )
  10808.             EXECUTE dbo.sp_replflush
  10809.  
  10810.     COMMIT TRANSACTION
  10811.     drop table #sysextendedarticlesview
  10812.     RETURN(0)
  10813. go
  10814.  
  10815. EXEC dbo.sp_MS_marksystemobject sp_changesubstatus
  10816. GO
  10817.  
  10818. print ''
  10819. print 'Creating procedure sp_addsubscription'
  10820. go
  10821. CREATE PROCEDURE sp_addsubscription (
  10822.     @publication sysname,                            /* publication name */
  10823.     @article sysname = 'all',                        /* article name */
  10824.     @subscriber sysname = NULL,                        /* subscriber name */
  10825.     @destination_db sysname = NULL,                /* destination database */
  10826.     @sync_type nvarchar (15) = 'automatic',                /* subscription sync type */
  10827.     @status sysname = NULL,                            /* subscription status */
  10828.     @subscription_type nvarchar(4) = 'push',                /* subscription type:
  10829.                                                         ** 'push' or 'pull' */
  10830.     -- SyncTran
  10831.     @update_mode           nvarchar(30)    = 'read only',    -- Can be 'read only', 'sync tran', 'queued tran', 'failover'
  10832.     @loopback_detection nvarchar(5) = NULL, -- 'true' or 'false'
  10833.     -- end SyncTran
  10834.  
  10835.     @frequency_type int = NULL,
  10836.     @frequency_interval int = NULL,
  10837.     @frequency_relative_interval int = NULL,
  10838.     @frequency_recurrence_factor int = NULL,
  10839.     @frequency_subday int = NULL,
  10840.     @frequency_subday_interval int = NULL,
  10841.     @active_start_time_of_day int = NULL,
  10842.     @active_end_time_of_day int = NULL,
  10843.     @active_start_date int = NULL,
  10844.     @active_end_date int = NULL,
  10845.     @optional_command_line nvarchar(4000) = NULL,
  10846.     
  10847.     @reserved nvarchar(10) = NULL,          /* reserved, used when calling from other system */
  10848.                                             /* stored procedures, it will be set to 'internal'.*/
  10849.                                             /* It should never be used directly */
  10850.     @enabled_for_syncmgr nvarchar(5) = 'false', /* Enabled for SYNCMGR: true or false */
  10851.     -- Agent offload
  10852.     @offloadagent bit = 0,
  10853.     @offloadserver sysname = NULL,
  10854.     -- End of agent offload
  10855.     -- DTS package name
  10856.     @dts_package_name sysname  = NULL,    /* value will be sent and validated at distributor */                                  
  10857.      @dts_package_password  sysname = NULL,
  10858.     @dts_package_location nvarchar(12) = N'distributor',
  10859.     @distribution_job_name sysname = NULL
  10860.    ) AS
  10861.  
  10862.     SET NOCOUNT ON
  10863.  
  10864.     /*
  10865.     ** Declarations.
  10866.     */
  10867.  
  10868.     DECLARE @artid int
  10869.     DECLARE @pre_creation_cmd tinyint
  10870.     DECLARE @none tinyint
  10871.     DECLARE @automatic tinyint
  10872.     DECLARE @cmd nvarchar(255)
  10873.     DECLARE @cmd2 nvarchar(255)
  10874.     DECLARE @inactive tinyint
  10875.     DECLARE @active tinyint
  10876.     DECLARE @subscribed tinyint
  10877.     DECLARE @manual tinyint
  10878.     DECLARE @pubid int
  10879.     DECLARE @retcode int
  10880.     DECLARE @srvid smallint
  10881.     DECLARE @subscriber_bit smallint
  10882.     DECLARE @sync_typeid tinyint
  10883.     DECLARE @non_sql_flag bit
  10884.     DECLARE @truncate tinyint
  10885.     DECLARE @sync_method tinyint
  10886.     DECLARE @char_bcp tinyint
  10887.     DECLARE @concurrent tinyint
  10888.     DECLARE @concurrent_char tinyint
  10889.     DECLARE @internal nvarchar(10)
  10890.     DECLARE @status_id tinyint
  10891.     DECLARE @virtual_id smallint
  10892.     DECLARE @subscription_type_id int /* 0 push, 1 pull */
  10893.     DECLARE @immediate_sync bit    /* publication type */
  10894.     DECLARE @count_subs int
  10895.     DECLARE @count_arts int
  10896.     DECLARE @distribution_jobid binary(16)
  10897.     DECLARE @pubstatus tinyint
  10898.     DECLARE @allow_anonymous bit
  10899.     DECLARE @immediate_sync_ready bit
  10900.     declare @loopback_detection_id bit
  10901.     declare @independent_agent_id bit
  10902.     DECLARE @platform_nt binary
  10903.             ,@artsrctabid int
  10904.  
  10905.     DECLARE @dsn_dbname sysname
  10906.     DECLARE @dts_package_enc_password nvarchar(524)
  10907.  
  10908.     -- SyncTran
  10909.     DECLARE @allow_sync_tran_id bit
  10910.     DECLARE @allow_queued_tran_id bit
  10911.     DECLARE @update_mode_id     tinyint -- 0 = read only, 1 = sync tran, 2 = queued tran, 3 = failover
  10912.                                         -- 4 = sqlqueued tran, 5 = sqlqueued failover
  10913.     DECLARE    @publication_queue_type int 
  10914.     -- end SyncTran
  10915.  
  10916.     /*
  10917.     ** Initializations.
  10918.     */
  10919.  
  10920.     SELECT @none = 2            /* Const: synchronization type 'none' */
  10921.     SELECT @automatic = 1       /* Const: synchronization type 'automatic' */
  10922.     SELECT @manual = 0          /* Const: synchronization type 'manual' */
  10923.     SELECT @inactive = 0        /* Const: subscription status 'inactive' */
  10924.     SELECT @subscribed = 1        /* Const: subscription status 'subscribed' */
  10925.     SELECT @active = 2        /* Const: subscription status 'arctive' */
  10926.     SELECT @subscriber_bit = 4  /* Const: subscription server status */
  10927.     SELECT @truncate = 3    /* Const: truncate pre-creation command */
  10928.     SELECT @char_bcp = 1    /* Const: character bcp sync method */
  10929.     SELECT @concurrent = 3  /* Const: concurrent sync method */
  10930.     SELECT @concurrent_char = 4  /* Const: concurrent char mode sync method */
  10931.     SELECT @virtual_id = -1 /* Const: virtual subscriber id */
  10932.     SELECT @internal = 'internal' /* Const: Flag of calling internally from system */
  10933.                                   /* stored procedures     */
  10934.     
  10935.     -- Change it  in 7.5 to avoid confusion, expecially in ole db case
  10936.     -- SELECT @dsn_dbname = 'DSN'
  10937.     SELECT @dsn_dbname = formatmessage(20586)
  10938.     SELECT @platform_nt = 0x1
  10939.  
  10940.     /*
  10941.     ** Parameter Check: @publication.
  10942.     ** Check to make sure that the publication exists and that it conforms
  10943.     ** to the rules for identifiers.
  10944.     ** set subscription_type for the publication
  10945.     */
  10946.  
  10947.     IF @publication IS NOT NULL
  10948.         BEGIN
  10949.             
  10950.             EXECUTE @retcode = dbo.sp_validname @publication
  10951.  
  10952.             IF @retcode <> 0
  10953.         RETURN (1)
  10954.  
  10955.             IF NOT EXISTS (SELECT * FROM syspublications WHERE name = @publication)
  10956.                 BEGIN
  10957.                     RAISERROR (20026, 11, -1, @publication)
  10958.                     RETURN (1)
  10959.                 END
  10960.  
  10961.         END
  10962.  
  10963.     /*
  10964.     ** Parameter Check: @subscription_type
  10965.     ** Valid values:
  10966.     ** push
  10967.     ** pull
  10968.     **
  10969.     */
  10970.  
  10971.     IF LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('push', 'pull')
  10972.         BEGIN
  10973.             RAISERROR (14128, 16, -1)    
  10974.             RETURN (1)
  10975.         END
  10976.  
  10977.     IF LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) = 'push'
  10978.         SELECT @subscription_type_id = 0
  10979.     ELSE 
  10980.         SELECT @subscription_type_id = 1
  10981.  
  10982.     /*
  10983.     ** Parameter Check: @offloadagent
  10984.     ** Valid values: 0 or 1 
  10985.     ** If @offloadagent = 1 then @subscription_type must be 'push'
  10986.     */
  10987.     IF (@offloadagent = 1 AND LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) <> 'push')
  10988.     BEGIN
  10989.         RAISERROR(21138, 16, -1)
  10990.         RETURN (1)
  10991.     END 
  10992.  
  10993.  
  10994.     /*
  10995.     ** Parameter Check: @offloadserver
  10996.     ** Make sure that @offlaod server doesn't contain any invalid characters
  10997.     */
  10998.     EXEC @retcode = sp_MSreplcheckoffloadserver @offloadserver
  10999.     IF @retcode<>0 OR @@error<>0
  11000.         RETURN (1)
  11001.     /*
  11002.     ** Security Check.
  11003.     */
  11004.  
  11005.     IF @subscription_type_id = 0 
  11006.     BEGIN
  11007.         exec @retcode = dbo.sp_MSreplcheck_publish
  11008.         if @@ERROR <> 0 or @retcode <> 0
  11009.             return(1)
  11010.     END
  11011.     ELSE
  11012.     BEGIN
  11013.         exec @retcode = dbo.sp_MSreplcheck_pull @publication
  11014.         if @@ERROR <> 0 or @retcode <> 0
  11015.             return(1)
  11016.     END
  11017.  
  11018.    declare @allow_dts bit
  11019.  
  11020.    SELECT @pubid = pubid, @sync_method = sync_method, 
  11021.         @immediate_sync = immediate_sync, @pubstatus = status, 
  11022.         @allow_anonymous = allow_anonymous, 
  11023.         @immediate_sync_ready = immediate_sync_ready,
  11024.         -- SyncTran
  11025.         @allow_sync_tran_id = allow_sync_tran,
  11026.         @allow_queued_tran_id = allow_queued_tran,
  11027.         @independent_agent_id = independent_agent,
  11028.         @allow_dts = allow_dts
  11029.         ,@publication_queue_type = queue_type
  11030.     FROM syspublications WHERE name = @publication
  11031.  
  11032.     select @srvid = srvid from master..sysservers where UPPER(srvname)=UPPER(@subscriber) collate database_default
  11033.  
  11034.     if exists (select name from sysobjects where name='sysmergesubscriptions')
  11035.         begin
  11036.             IF exists (select name from sysextendedarticlesview where pubid=@pubid and 
  11037.                 objid in (select objid from sysmergeextendedarticlesview where 
  11038.                     pubid in (select pubid from sysmergesubscriptions where db_name=@destination_db and srvid=@srvid)))
  11039.             begin
  11040.                 RAISERROR(21281, 16, -1, @publication, @destination_db)
  11041.                 return (1)
  11042.             end
  11043.         end
  11044.  
  11045.  
  11046.     IF @pubid IS NULL
  11047.         BEGIN
  11048.             RAISERROR (14043, 16, -1, '@pubid')
  11049.             RETURN (1)
  11050.         END
  11051.  
  11052.     /* 
  11053.     ** If publication is of concurrent sync, then all articles must
  11054.     ** be subscribed to
  11055.     */
  11056.     IF @sync_method IN( @concurrent, @concurrent_char) AND
  11057.        LOWER(@article) != 'all' AND
  11058.        @reserved != @internal
  11059.     BEGIN
  11060.         RAISERROR( 14100, 16, -1 )
  11061.         RETURN (1)
  11062.     END
  11063.  
  11064.     /* 
  11065.     ** Check to see if the desired subscription type is allowed
  11066.     */
  11067.     /* 
  11068.     ** push 
  11069.     ** Virtual subscriptions are always push type
  11070.     */
  11071.     IF @subscription_type_id = 0 AND @subscriber IS NOT NULL
  11072.     BEGIN
  11073.         IF NOT EXISTS (SELECT * from syspublications where
  11074.             allow_push = 1 AND
  11075.             pubid = @pubid)
  11076.         BEGIN
  11077.             RAISERROR (20012, 16, -1, @subscription_type, @publication)    
  11078.             RETURN (1)
  11079.         END
  11080.     END
  11081.         
  11082.     /* pull */
  11083.     IF @subscription_type_id = 1 AND @subscriber IS NOT NULL
  11084.     BEGIN
  11085.         IF NOT EXISTS (SELECT * from syspublications where
  11086.             allow_pull = 1 AND
  11087.             pubid = @pubid)
  11088.         BEGIN
  11089.             RAISERROR (20012, 16, -1, @subscription_type, @publication)    
  11090.             RETURN (1)
  11091.         END
  11092.     END
  11093.  
  11094.  /*
  11095.     ** Parameter Check: @subscriber.
  11096.     **
  11097.     ** Check if the server exists and that it is a subscription server.
  11098.     **
  11099.     ** @subscriber is NULL represent virtual subscription, which is not allowed
  11100.     ** in following case:
  11101.     ** 1. Non-immediate-sync publication
  11102.     ** 2. the stored procedure is not in the internal usage mode 
  11103.     **        (called by system stored procedures)
  11104.     ** 3. non push mode
  11105.     ** 
  11106.     */
  11107.  
  11108.     IF  @subscriber IS NULL AND (
  11109.         @immediate_sync = 0 OR
  11110.         @subscription_type_id <> 0 OR
  11111.         @reserved <> @internal)
  11112.         BEGIN
  11113.             RAISERROR (14043, 16, -1, '@subscriber')
  11114.             RETURN (1)
  11115.         END
  11116.  
  11117.  
  11118.     IF @subscriber IS NULL
  11119.         BEGIN
  11120.         /* set virtual subscriber ID */
  11121.             SELECT @srvid = @virtual_id 
  11122.             select @non_sql_flag = 0
  11123.         END
  11124.     ELSE
  11125.         BEGIN
  11126.             /* validate name and get subscriber ID  and server status  */
  11127.             EXECUTE @retcode = dbo.sp_validname @subscriber
  11128.  
  11129.             IF @retcode <> 0
  11130.             RETURN (1)
  11131.  
  11132.             select @srvid = null
  11133.             SELECT @srvid = srvid, @non_sql_flag = 
  11134.                 case when srvproduct = N'MSREPL-NONSQL' then 1
  11135.                 else 0 end
  11136.               FROM master..sysservers
  11137.              WHERE UPPER(srvname) = UPPER(@subscriber) collate database_default
  11138.                AND (srvstatus & @subscriber_bit) <> 0
  11139.  
  11140.             IF @srvid IS NULL
  11141.                 BEGIN
  11142.                     RAISERROR (14010, 16, -1)
  11143.                    RETURN (1)
  11144.                 END
  11145.         END
  11146.  
  11147.     /*
  11148.     ** Parameter Check: @destination_db.
  11149.     ** @destination_db can not be all. 
  11150.     ** Set @destination_db to current database if not specified.  Make
  11151.     ** sure that the @destination_db conforms to the rules for identifiers.
  11152.     */
  11153.  
  11154.     if LOWER(@destination_db) = 'all'
  11155.     BEGIN
  11156.         RAISERROR (14032, 16, -1, '@destination_db')
  11157.         RETURN (1)
  11158.     END
  11159.  
  11160.     IF @destination_db IS not NULL
  11161.     begin
  11162.         EXECUTE @retcode = dbo.sp_validname @destination_db
  11163.         IF @retcode <> 0
  11164.         RETURN (1)
  11165.     end
  11166.  
  11167.     /*
  11168.     ** Parameter Check:  @article
  11169.     */
  11170.  
  11171.     /* @article can not be null     */
  11172.     IF @article IS NULL
  11173.         BEGIN
  11174.             RAISERROR (14043, 16, -1, '@article')
  11175.             RETURN (1)
  11176.         END
  11177.  
  11178.     -- Queued Tran
  11179.     -- SyncTran
  11180.     /*
  11181.     ** Parameter check: @update_mode
  11182.     */
  11183.     IF @update_mode IS NULL OR LOWER(@update_mode collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('read only', 'sync tran', 'queued tran', 'failover')
  11184.     BEGIN
  11185.         RAISERROR (20502, 16, -1, '@update_mode')
  11186.         RETURN (1)
  11187.     END
  11188.  
  11189.     IF (LOWER(@update_mode collate SQL_Latin1_General_CP1_CS_AS) = 'sync tran') 
  11190.     BEGIN
  11191.         SELECT @update_mode_id = 1
  11192.        
  11193.         -- Check if publication allows this option
  11194.         IF @allow_sync_tran_id <> 1
  11195.         BEGIN
  11196.             RAISERROR (20503, 16, -1, '@update_mode', 'sp_addsubscription','sync tran')
  11197.             RETURN (1)
  11198.         END
  11199.     END
  11200.     ELSE IF (LOWER(@update_mode collate SQL_Latin1_General_CP1_CS_AS) = 'queued tran')
  11201.     BEGIN        
  11202.         SELECT @update_mode_id = case 
  11203.             when (@publication_queue_type = 2) then 4
  11204.             else 2 end
  11205.        
  11206.         -- Check if publication allows this option
  11207.         -- If the publication allow synctran, it allows queued tran.
  11208.         IF @allow_queued_tran_id <> 1
  11209.         BEGIN
  11210.             RAISERROR (20503, 16, -1, '@update_mode', 'sp_addsubscription', 'queued tran')
  11211.             RETURN (1)
  11212.         END
  11213.     END
  11214.     ELSE IF (LOWER(@update_mode collate SQL_Latin1_General_CP1_CS_AS) = 'failover')
  11215.     BEGIN
  11216.         SELECT @update_mode_id = case
  11217.             when (@publication_queue_type = 2) then 5
  11218.             else 3 end
  11219.        
  11220.         -- Check if publication allows this option
  11221.         IF @allow_sync_tran_id <> 1
  11222.         BEGIN
  11223.             RAISERROR (20503, 16, -1, '@update_mode', 'sp_addsubscription', 'sync tran')
  11224.             RETURN (1)
  11225.         END
  11226.  
  11227.         -- Check if publication allows this option
  11228.         IF @allow_queued_tran_id <> 1
  11229.         BEGIN
  11230.             RAISERROR (20503, 16, -1, '@update_mode', 'sp_addsubscription','queued tran')
  11231.             RETURN (1)
  11232.         END
  11233.     END
  11234.     ELSE 
  11235.     BEGIN
  11236.         SELECT @update_mode_id = 0
  11237.     END
  11238.     -- end SyncTran
  11239.     -- end Queued Tran
  11240.  
  11241.     /*
  11242.     ** Parameter Check: @dts_package_location
  11243.     ** Valid values:
  11244.     ** distributor
  11245.     ** subscriber
  11246.     **
  11247.     */
  11248.     IF LOWER(@dts_package_location collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('distributor', 'subscriber')
  11249.     BEGIN
  11250.         RAISERROR(21179, 16, -1)    
  11251.         RETURN (1)
  11252.     END
  11253.  
  11254.     declare @dts_package_location_id int
  11255.  
  11256.     IF LOWER(@dts_package_location collate SQL_Latin1_General_CP1_CS_AS) = 'distributor'
  11257.         SELECT @dts_package_location_id = 0
  11258.     ELSE 
  11259.         SELECT @dts_package_location_id = 1
  11260.  
  11261.     -- Have to be a push, non updatable  subscription to set DTS package name
  11262.     if @dts_package_name is not null
  11263.     begin
  11264.         if    @subscription_type_id != 0
  11265.         begin
  11266.             RAISERROR(21181, 16, -1)    
  11267.             RETURN (1)
  11268.         end
  11269.         if    @allow_dts = 0
  11270.         begin
  11271.             RAISERROR(21178, 16, -1)    
  11272.             RETURN (1)
  11273.         end
  11274.     end
  11275.     
  11276.     /** For immediate_sync publication, @article has to be 'all'     */
  11277.     IF NOT @reserved = @internal AND @immediate_sync = 1
  11278.         AND NOT LOWER(@article) = 'all'
  11279.         BEGIN
  11280.             RAISERROR (14122, 16, -1)
  11281.             RETURN (1)
  11282.         END
  11283.  
  11284.     /* 
  11285.     ** For full subscription, check to see if  subscriptions
  11286.     ** to ALL the articles exist before expanding parameter @article.
  11287.     **
  11288.     */
  11289.     IF LOWER(@article) = 'all' AND @reserved <> @internal AND
  11290.         EXISTS (SELECT * FROM syspublications WHERE pubid = @pubid)
  11291.     BEGIN
  11292.         SELECT @count_arts = count(*) FROM sysextendedarticlesview art
  11293.             WHERE art.pubid = @pubid 
  11294.  
  11295.         if @count_arts = 0
  11296.         BEGIN
  11297.             RAISERROR (14124, 16, -1)
  11298.             RETURN(1)
  11299.         END
  11300.  
  11301.         SELECT @count_subs = count(*) FROM syssubscriptions sub, 
  11302.                   sysextendedarticlesview art
  11303.             WHERE sub.srvid = @srvid
  11304.               AND sub.srvid >= 0
  11305.               AND sub.dest_db = @destination_db --or @non_sql_flag <> 0)
  11306.               AND sub.artid = art.artid
  11307.               AND art.pubid = @pubid
  11308.  
  11309.         IF @count_arts = @count_subs
  11310.         BEGIN
  11311.               RAISERROR (14058, 16, -1)
  11312.               RETURN (1)
  11313.         END
  11314.     END
  11315.  
  11316.     /* 
  11317.     ** Real subscription to inactive publicaton is not allowed
  11318.     ** Note, subscriptions to the new article will be added automatically
  11319.     ** for immediate_sync publications. At that time, the publication may not
  11320.     ** be active.
  11321.     */
  11322.  
  11323.     IF  @srvid <> @virtual_id AND @pubstatus = 0 AND @reserved <> @internal
  11324.         BEGIN
  11325.             RAISERROR (21000, 16, -1)
  11326.             RETURN (1)
  11327.         END
  11328.  
  11329.  
  11330.     -- If the publication is 'allow_dts', push subscription has to specify a DTS package.
  11331.     -- Error check that disallow ODBC subscriber to subscriber with DTS package
  11332.     -- is at the distributor.
  11333.     -- Show dts error first, otherwise user will get 21060 below which is confusing
  11334.     IF @allow_dts <> 0 and @dts_package_name is null and @subscriber IS not NULL and
  11335.         @reserved is null and @subscription_type_id = 0
  11336.     begin
  11337.         raiserror(21213, 16, -1)
  11338.         return(1)
  11339.     end
  11340.  
  11341.     /* 
  11342.     ** Do special things for DSN subscribers.
  11343.     */
  11344.     IF @subscriber IS NOT NULL AND @non_sql_flag <> 0
  11345.     BEGIN
  11346.         -- DSN or oledb subscriber not using DTS 
  11347.         -- cannot subscribe to native mode or concurrent snapshot publication
  11348.         IF @sync_method <> @char_bcp and @dts_package_name is null
  11349.         BEGIN
  11350.             RAISERROR (14095, 16, -1, @publication, @subscriber)
  11351.             RETURN (1)
  11352.         END
  11353.  
  11354.         -- DSN subscriber cannot subscribe with 'Sync Update'
  11355.         IF @update_mode_id <> 0
  11356.         BEGIN
  11357.             RAISERROR (21032, 16, -1, @subscriber)
  11358.             RETURN (1)
  11359.         END
  11360.  
  11361.         -- DSN subscriber cannot subscribe to article using custom procs
  11362.         -- or articles using parameterized statements
  11363.         -- ( only run this test during execs when the article name is actually specified )
  11364.         IF( LOWER( @article ) <> 'all' )
  11365.         BEGIN
  11366.             --IF EXISTS ( select * from sysextendedarticlesview sa, syspublications sp
  11367.                         --where sa.pubid = sp.pubid 
  11368.                         --and sp.name = @publication
  11369.                         --and sa.name = @article
  11370.                         --and ( ins_cmd like '%call%' or upd_cmd like '%call%' or del_cmd like '%call%' ) )
  11371.             --BEGIN
  11372.                 --RAISERROR(21051, 16, -1, @subscriber)
  11373.                 --RETURN (1)
  11374.             --END
  11375.             
  11376.             declare @art_status tinyint
  11377.  
  11378.             select @art_status = sa.status, @artsrctabid = sa.objid 
  11379.             from sysarticles sa, syspublications sp
  11380.                 where sa.pubid = sp.pubid 
  11381.                 and sp.name = @publication
  11382.                 and sa.name = @article
  11383.  
  11384.             -- OLEDB or ODBC subscriber can not subscribe to article with parameterized command 
  11385.             -- unless using DTS 
  11386.             IF @dts_package_name is null and @art_status & 16 = 16 
  11387.             BEGIN
  11388.                 RAISERROR(21060, 16, -1, @subscriber)
  11389.                 RETURN (1)
  11390.             END
  11391.  
  11392.             -- OLEDB or ODBC subscribers can not subscriber to article with subscriber managed
  11393.             -- timestamp column
  11394.             if @art_status & 32 = 32
  11395.             begin
  11396.                 raiserror(21249, 16, -1, @article, @publication)
  11397.                 return (1)
  11398.             end
  11399.  
  11400.         END
  11401.     END
  11402.  
  11403.     -- DNS may define db.  If no db given, specify that DSN default should be used.
  11404.     -- use internal values
  11405.     if @subscriber IS NOT NULL and @destination_db is NULL
  11406.     begin
  11407.         IF @non_sql_flag <> 0 
  11408.             SELECT @destination_db = @dsn_dbname
  11409.         else
  11410.             SELECT @destination_db = DB_NAME()
  11411.     end
  11412.  
  11413.     -- if we're subscribing to a dump type publication, error
  11414.     -- out if this subscriber has any other subscriptions to publications
  11415.     -- other than this one
  11416.  
  11417.     IF @sync_method = 2
  11418.     BEGIN
  11419.         IF EXISTS( SELECT * FROM syssubscriptions sub, sysextendedarticlesview art
  11420.                 WHERE sub.srvid = @srvid
  11421.                   AND sub.srvid >= 0
  11422.                   AND sub.dest_db = @destination_db
  11423.                   AND sub.artid = art.artid
  11424.                   AND art.pubid != @pubid )
  11425.         BEGIN
  11426.             RAISERROR(21144, 16, -1)
  11427.             RETURN 1
  11428.         END
  11429.     END
  11430.  
  11431.     -- else if we're subscribing to a char or native mode publication, 
  11432.     -- error out if the subscriber is subscribed to any dump type publications
  11433.     ELSE
  11434.     BEGIN
  11435.         IF EXISTS( SELECT * FROM syssubscriptions sub, sysextendedarticlesview art, syspublications pub
  11436.                 WHERE sub.srvid = @srvid
  11437.                   AND sub.srvid >= 0
  11438.                   AND sub.dest_db = @destination_db
  11439.                   AND sub.artid = art.artid
  11440.                   AND art.pubid != @pubid
  11441.                   AND pub.pubid = art.pubid
  11442.                   AND pub.sync_method = 2 )
  11443.  
  11444.         BEGIN
  11445.             RAISERROR(21145, 16, -1, @publication )
  11446.             RETURN 1
  11447.         END
  11448.     END
  11449.  
  11450.  
  11451.     IF LOWER(@article) = 'all' 
  11452.     /*
  11453.     ** Get all articles in the publication that are not subscribed to
  11454.     ** by the @subscriber
  11455.     */
  11456.     BEGIN
  11457.             /*
  11458.             ** Make the operation atomic. This is to prevent multiple subscription_type
  11459.             ** from one subscriber on an immediate_sync publication
  11460.             */
  11461.             BEGIN TRAN 
  11462.  
  11463.             DECLARE hCx CURSOR LOCAL FAST_FORWARD FOR  SELECT DISTINCT a.name
  11464.                 FROM sysextendedarticlesview a, syspublications b  
  11465.                 WHERE a.pubid = b.pubid 
  11466.                 AND b.name = @publication
  11467.                 AND NOT EXISTS (SELECT * from syssubscriptions s 
  11468.                     WHERE s.artid = a.artid AND s.status <> 0 AND s.srvid = @srvid
  11469.                     AND s.dest_db = @destination_db)
  11470.             FOR READ ONLY
  11471.  
  11472.             EXECUTE (@cmd + @cmd2)
  11473.             OPEN hCx
  11474.             FETCH hCx INTO @article
  11475.  
  11476.             WHILE (@@fetch_status <> -1)
  11477.                 BEGIN
  11478.                     EXECUTE @retcode = dbo.sp_addsubscription 
  11479.                                 @publication       = @publication,
  11480.                                 @article        = @article,
  11481.                                 @subscriber     = @subscriber,
  11482.                                 @destination_db = @destination_db,
  11483.                                 @sync_type      = @sync_type,
  11484.                                 @status            = @status,
  11485.                                 @subscription_type = @subscription_type,
  11486.                                 @reserved       = @internal,
  11487.                                 -- SyncTran
  11488.                                 @update_mode    = @update_mode,      
  11489.                                 -- end SyncTran
  11490.                                 @loopback_detection = @loopback_detection,
  11491.                                 @frequency_type  = @frequency_type,
  11492.                                 @frequency_interval  = @frequency_interval,
  11493.                                 @frequency_relative_interval  = @frequency_relative_interval,
  11494.                                 @frequency_recurrence_factor  = @frequency_recurrence_factor,
  11495.                                 @frequency_subday  = @frequency_subday,
  11496.                                 @frequency_subday_interval  = @frequency_subday_interval,
  11497.                                 @active_start_time_of_day  = @active_start_time_of_day,
  11498.                                 @active_end_time_of_day  = @active_end_time_of_day,
  11499.                                 @active_start_date  = @active_start_date,
  11500.                                 @active_end_date  = @active_end_date,
  11501.                                 @optional_command_line = @optional_command_line,
  11502.                                 @offloadserver = @offloadserver,
  11503.                                 @offloadagent = @offloadagent,
  11504.                                 @dts_package_name = @dts_package_name,
  11505.                                 @dts_package_password = @dts_package_password,
  11506.                                 @dts_package_location = @dts_package_location,
  11507.                                 @distribution_job_name = @distribution_job_name
  11508.     
  11509.  
  11510.                     IF @@error <> 0 OR @retcode <> 0
  11511.                     BEGIN
  11512.                        CLOSE hCx
  11513.                        DEALLOCATE hCx
  11514.                        if @@trancount > 0
  11515.                             ROLLBACK TRAN 
  11516.                        RETURN (1)
  11517.                     END
  11518.                     FETCH hCx INTO @article
  11519.                 END
  11520.             CLOSE hCx
  11521.             DEALLOCATE hCx
  11522.  
  11523.             COMMIT TRAN
  11524.  
  11525.             RETURN (0)
  11526.         END
  11527.  
  11528.    
  11529.     /* After 'all' being expanded, check to make sure that the article exists, 
  11530.     ** is not NULL, and conforms to the rules for identifiers.
  11531.     */
  11532.     /*
  11533.     EXECUTE @retcode = dbo.sp_validname @article
  11534.     IF @retcode <> 0
  11535.     RETURN (1)
  11536.     */
  11537.  
  11538.     declare @dest_owner sysname
  11539.  
  11540.     SELECT @artid = artid, @pre_creation_cmd = pre_creation_cmd,
  11541.         @dest_owner = dest_owner
  11542.     FROM sysextendedarticlesview
  11543.     WHERE name = @article
  11544.     AND pubid = @pubid
  11545.  
  11546.     IF NOT EXISTS (SELECT *
  11547.                              FROM sysextendedarticlesview
  11548.                             WHERE artid = @artid
  11549.                               AND pubid = @pubid)
  11550.         BEGIN
  11551.             RAISERROR (20027, 11, -1, @article)
  11552.             RETURN (1)
  11553.         END
  11554.  
  11555.  
  11556.     /*
  11557.     ** If the subscriber is an ODBC DSN, do not allow subscriptions to
  11558.     ** articles with a "truncate" pre_creation_cmd.
  11559.     */
  11560.     IF @non_sql_flag <> 0 AND @pre_creation_cmd = @truncate
  11561.         BEGIN
  11562.             RAISERROR (14094, 16, -1, @article, @subscriber)
  11563.             RETURN (1)
  11564.         END
  11565.  
  11566.     IF @non_sql_flag <> 0 AND @dest_owner is not null and @dest_owner <> N''
  11567.         BEGIN
  11568.             --RAISERROR (21039, 16, -1, @article, @subscriber)
  11569.             -- YWU: UNDONE fix the message after Beta2
  11570.             RAISERROR (21039, 16, -1)
  11571.             RETURN (1)
  11572.         END
  11573.  
  11574.    /*
  11575.    ** Parameter Check: @sync_type.
  11576.    ** Set sync_typeid based on the @sync_type specified.
  11577.    **
  11578.    **   sync_typeid     sync_type
  11579.    **   ===========     =========
  11580.    **             0     manual
  11581.    **             1     automatic
  11582.    **             2     none
  11583.    */
  11584.  
  11585.  
  11586.    IF LOWER(@sync_type collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('automatic', 'manual', 'none')
  11587.        BEGIN
  11588.            RAISERROR (14052, 16, -1)
  11589.            RETURN (1)
  11590.        END
  11591.  
  11592.    IF LOWER(@sync_type collate SQL_Latin1_General_CP1_CS_AS) = 'manual'
  11593.        BEGIN
  11594.            RAISERROR (14123, 16, -1)
  11595.            RETURN (1)
  11596.        END
  11597.  
  11598.  
  11599.    IF LOWER(@sync_type collate SQL_Latin1_General_CP1_CS_AS) = 'automatic'
  11600.    BEGIN
  11601.         SELECT @sync_typeid = @automatic
  11602.    END
  11603.    ELSE
  11604.    BEGIN
  11605.         SELECT @sync_typeid = @none
  11606.    END
  11607.  
  11608.  
  11609.     /*
  11610.     ** Parameter Check: @status
  11611.     ** If the publication is immediate_sync type and sync_type is automatic
  11612.     ** the status has to be NULL.
  11613.     ** Note for 6x backward compatibility, don't do the check for non immediate_sync
  11614.     ** publication
  11615.     */
  11616.     IF @immediate_sync = 1 and @sync_typeid = @automatic AND 
  11617.         @status IS NOT NULL
  11618.     BEGIN
  11619.           RAISERROR (14129, 16, -1)
  11620.           RETURN (1)
  11621.     END
  11622.  
  11623.     /*
  11624.     ** Parameter Check:  @loopback_detection
  11625.     */
  11626.     IF @loopback_detection is not null and LOWER(@loopback_detection collate SQL_Latin1_General_CP1_CS_AS) 
  11627.         NOT IN ('true', 'false')
  11628.     BEGIN
  11629.         RAISERROR (14148, 16, -1, '@loopback_detection')
  11630.         RETURN (1)
  11631.     END
  11632.  
  11633.     IF  LOWER(@loopback_detection collate SQL_Latin1_General_CP1_CS_AS) = 'true'  
  11634.         SELECT @loopback_detection_id = 1
  11635.     ELSE IF LOWER(@loopback_detection collate SQL_Latin1_General_CP1_CS_AS) = 'false' 
  11636.         SELECT @loopback_detection_id = 0
  11637.     ELSE 
  11638.     -- if @loopback_detection is null, we will chose the value
  11639.     begin
  11640.         -- turn on loopback detection for sync and queued
  11641.         if @update_mode_id in (1,2,3,4,5) 
  11642.             select @loopback_detection_id = 1
  11643.         else
  11644.             select @loopback_detection_id = 0
  11645.     end
  11646.  
  11647.     select @dts_package_enc_password = @dts_package_password
  11648.     if @dts_package_password is not null
  11649.     begin
  11650.         EXEC @retcode = master.dbo.xp_repl_encrypt @dts_package_enc_password OUTPUT
  11651.         IF @@error <> 0 OR @retcode <> 0
  11652.             return 1
  11653.     end
  11654.  
  11655.     --
  11656.     -- For updating subscriptions (immediate)
  11657.     -- Check if there exists an subscription to the same
  11658.     -- dest_db which contain at least one article which has 
  11659.     -- the same source_table as the current article - 
  11660.     -- If yes then raise a warning
  11661.     -- NOTE : this restriction is due to the fact that loopback
  11662.     -- detection happens at database level and hence for updating
  11663.     -- subscriptions, we can lose the updates made in one subscription
  11664.     -- w.r.t. the other subscription
  11665.     --
  11666.     if (@update_mode_id = 1)
  11667.     begin
  11668.         if exists (select * from dbo.syssubscriptions 
  11669.             where srvid = @srvid and dest_db = @destination_db and artid in 
  11670.                 (select artid from dbo.sysarticles 
  11671.                     where objid = (select objid from sysarticles where artid = @artid)))
  11672.         begin
  11673.             raiserror(21293, 10, 1, @article, @destination_db)
  11674.         end
  11675.     end
  11676.  
  11677.     /*
  11678.     ** Add subscription to syssubscriptions
  11679.     */
  11680.     begin tran
  11681.     save TRAN addsubscription
  11682.  
  11683.     /*
  11684.     ** If no subscription exists, add it to syssubscriptions.
  11685.     */
  11686.     IF NOT EXISTS (SELECT *
  11687.                      FROM syssubscriptions
  11688.                     WHERE srvid = @srvid
  11689.                       AND artid = @artid
  11690.                       AND dest_db = @destination_db )--or @non_sql_flag <> 0))
  11691.         BEGIN
  11692.        INSERT syssubscriptions (artid,
  11693.                                     srvid,
  11694.                                     dest_db,
  11695.                                     login_name,
  11696.                                     status,
  11697.                                     sync_type,
  11698.                                     subscription_type,
  11699.                                     distribution_jobid,
  11700.                                     -- SyncTran
  11701.                                     update_mode,
  11702.                                     loopback_detection,
  11703.                                     queued_reinit)
  11704.                                  /*  timestamp) */
  11705.        VALUES (@artid,
  11706.                    @srvid,
  11707.                    @destination_db,    
  11708.                    suser_sname(suser_sid()),
  11709.                    @inactive,
  11710.                    @sync_typeid,
  11711.                    @subscription_type_id,
  11712.                    0,
  11713.                    -- SyncTran
  11714.                    @update_mode_id,
  11715.                    @loopback_detection_id,
  11716.                    1)
  11717.            /*  NULL) */
  11718.  
  11719.        IF @@ERROR <> 0
  11720.            BEGIN
  11721.                 if @@trancount > 0
  11722.                 begin
  11723.                     ROLLBACK TRAN  addsubscription
  11724.                     commit tran
  11725.                 end
  11726.                 RAISERROR (14057, 16, -1)
  11727.                 RETURN (1)
  11728.            END
  11729.         END
  11730.     ELSE
  11731.        BEGIN
  11732.           RAISERROR (14058, 16, -1)
  11733.           if @@trancount > 0
  11734.             begin
  11735.                 ROLLBACK TRAN  addsubscription
  11736.                 commit tran
  11737.             end
  11738.           RETURN (1)
  11739.        END
  11740.  
  11741.     /*
  11742.     ** If the @status was not provided determine the default value.
  11743.     ** If the @sync_type = 'none' then the subscription defaults to 'active'.
  11744.     ** Else the subscription defaults to 'subscribed'.
  11745.     */
  11746.     IF @status IS NULL
  11747.     BEGIN
  11748.         IF @sync_typeid = @none    
  11749.             SELECT @status = 'active'
  11750.         ELSE
  11751.             SELECT @status = 'subscribed'
  11752.     END
  11753.  
  11754.  
  11755.     /*
  11756.     ** Set publication subscription status.
  11757.     */
  11758.     EXEC @retcode = dbo.sp_changesubstatus
  11759.     @publication = @publication,
  11760.     @article     = @article,
  11761.     @subscriber  = @subscriber,
  11762.     @status      = @status,
  11763.     @destination_db = @destination_db,
  11764.     
  11765.     @frequency_type  = @frequency_type,
  11766.     @frequency_interval  = @frequency_interval,
  11767.     @frequency_relative_interval  = @frequency_relative_interval,
  11768.     @frequency_recurrence_factor  = @frequency_recurrence_factor,
  11769.     @frequency_subday  = @frequency_subday,
  11770.     @frequency_subday_interval  = @frequency_subday_interval,
  11771.     @active_start_time_of_day  = @active_start_time_of_day,
  11772.     @active_end_time_of_day  = @active_end_time_of_day,
  11773.     @active_start_date  = @active_start_date,
  11774.     @active_end_date  = @active_end_date,
  11775.     @optional_command_line = @optional_command_line,
  11776.     @distribution_jobid = @distribution_jobid OUTPUT,
  11777.     @offloadagent = @offloadagent,
  11778.     @offloadserver = @offloadserver,
  11779.     @dts_package_name = @dts_package_name,
  11780.     @dts_package_password = @dts_package_enc_password,
  11781.     @dts_package_location = @dts_package_location_id,
  11782.     @distribution_job_name = @distribution_job_name  
  11783.     
  11784.     IF @@error <> 0 OR @retcode <> 0
  11785.     BEGIN
  11786.         if @@trancount > 0
  11787.         begin
  11788.             ROLLBACK TRAN  addsubscription
  11789.             commit tran
  11790.         end
  11791.        RAISERROR (14057, 16, -1)
  11792.        RETURN (1)
  11793.     END
  11794.  
  11795.     UPDATE syssubscriptions SET 
  11796.         distribution_jobid = @distribution_jobid where
  11797.         artid = @artid AND
  11798.         srvid = @srvid AND
  11799.         dest_db = @destination_db            
  11800.  
  11801.     IF @@error <> 0
  11802.     BEGIN
  11803.         if @@trancount > 0
  11804.         begin
  11805.             ROLLBACK TRAN  addsubscription
  11806.             commit tran
  11807.         end
  11808.        RETURN (1)
  11809.     END
  11810.  
  11811.  
  11812.     /*
  11813.     ** If possible, activate the real subscriptions on immediate_sync publication
  11814.     ** immediately. Also, activate the virtual subscriptions on 
  11815.     ** anonymous publications immediately.
  11816.     ** We change the subscription status from 'subscribed' to 'active' so that 
  11817.     ** sp_MSupdate_subscription will be called, which will set the subscription's
  11818.     ** xactid_ts to the snapshot xactid_ts of virtual subscriptions. This means that
  11819.     ** we have to call sp_changesubstatus again here. We can not combine two calls 
  11820.     ** into ONE !!!
  11821.     **
  11822.     ** Activate the subscription immediately if 
  11823.     ** 1. The publication is immediate_sync type
  11824.     ** 2. sync_type is 'automatic'
  11825.     ** AND
  11826.     ** 1. The subscription is real
  11827.     ** 2. The snapshot has completed once
  11828.     ** 3. The subscription is the last subscription added to the publication (subscription for
  11829.     ** the last article). This is to guarantee the subscription status of all the articles
  11830.     ** in the publication be activate in one transaction at the distributor. This is
  11831.     ** to prevent the distribution agent from picking up partial subscriptions. 
  11832.     ** Note that this SP will be called with @article = 'all'
  11833.     ** OR
  11834.     ** 1. The publication is active
  11835.     ** 2. The publication is allow_anonymous
  11836.     ** 3. The subscription is virtual
  11837.     ** 
  11838.     */
  11839.     
  11840.     IF  @sync_typeid = @automatic AND @immediate_sync = 1 AND
  11841.         
  11842.         ((@srvid <> @virtual_id AND 
  11843.         @immediate_sync_ready = 1 AND
  11844.         NOT EXISTS (select * from sysextendedarticlesview art where
  11845.                     art.pubid = @pubid and
  11846.                     not exists (select * from syssubscriptions sub
  11847.                         where sub.artid = art.artid and
  11848.                               sub.srvid = @srvid and
  11849.                               sub.dest_db = @destination_db))) OR
  11850.  
  11851.         (@pubstatus = 1 and @srvid = @virtual_id and @allow_anonymous = 1))
  11852.     BEGIN
  11853.         DECLARE @article_ex sysname
  11854.         IF @srvid <> @virtual_id
  11855.             SELECT @article_ex = '%'
  11856.         ELSE
  11857.             SELECT @article_ex = @article
  11858.  
  11859.         /*
  11860.         ** Set publication subscription status.
  11861.         */
  11862.         EXEC @retcode = dbo.sp_changesubstatus
  11863.         @publication = @publication,
  11864.         @article     = @article_ex,
  11865.         @subscriber  = @subscriber,
  11866.         @status      = 'active',
  11867.         @destination_db = @destination_db,
  11868.         @offloadagent = @offloadagent,
  11869.         @offloadserver = @offloadserver
  11870.  
  11871.         IF @@error <> 0 OR @retcode <> 0
  11872.         BEGIN
  11873.             if @@trancount > 0
  11874.             begin
  11875.                 ROLLBACK TRAN  addsubscription
  11876.                 commit tran
  11877.             end
  11878.            RAISERROR (14057, 16, -1)
  11879.            RETURN (1)
  11880.         END
  11881.     END
  11882.  
  11883.     /* Conditional support for MobileSync */
  11884.     if LOWER(@enabled_for_syncmgr collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  11885.     BEGIN
  11886.         /* MobileSync Support */
  11887.         declare @distributor_server                 sysname
  11888.         declare @distributor_security_mode          int
  11889.         declare @distributor_login                  sysname
  11890.         declare @distributor_password               sysname
  11891.         declare @publisher_db sysname
  11892.         
  11893.         set @publisher_db = DB_NAME()
  11894.         /* 
  11895.         ** The registry entry needs to be created only for push subscriptions -  
  11896.         ** i.e - need not be called when a pull subscription is created at the 
  11897.         ** subscriber and sp_addmergesubscription is being called then.
  11898.         */
  11899.         IF LOWER(@subscription_type collate SQL_Latin1_General_CP1_CS_AS) = 'push'
  11900.         BEGIN
  11901.             EXECUTE @retcode = dbo.sp_helpdistributor
  11902.                 @distributor = @distributor_server OUTPUT               /* Distributor RPC server name */
  11903.  
  11904.             IF @@ERROR <> 0 or @retcode <> 0
  11905.                 BEGIN
  11906.                     if @@trancount > 0
  11907.                         ROLLBACK TRAN  addsubscription
  11908.                     RAISERROR (14057, 16, -1)
  11909.                     RETURN (1)
  11910.                 END
  11911.  
  11912.             -- Always use integrated security on winNT
  11913.             if (@platform_nt = platform() & @platform_nt )
  11914.                 begin
  11915.                     set @distributor_security_mode = 1
  11916.                 end
  11917.             -- For Win9x the dist publisher and distributor are the same machine                
  11918.             else
  11919.                 begin
  11920.                     select  @distributor_security_mode = 0,
  11921.                         @distributor_login  = login,
  11922.                         @distributor_password = password
  11923.                     from msdb..MSdistpublishers where UPPER(name) = UPPER(@@servername) collate database_default
  11924.                 end
  11925.  
  11926.  
  11927.             /* Call sp_MSregistersubscription so that the subscription can be synchronized via Onestop etc. */
  11928.             declare @subscription_id uniqueidentifier
  11929.             set @subscription_id = convert(uniqueidentifier, @distribution_jobid)
  11930.             exec @retcode = dbo.sp_MSregistersubscription @replication_type = 1,
  11931.                                     @publisher = @@SERVERNAME,
  11932.                                     @publisher_db = @publisher_db,
  11933.                                     @publication = @publication,
  11934.                                     @subscriber = @subscriber,
  11935.                                     @subscriber_db = @destination_db,
  11936.                                     @distributor = @distributor_server,
  11937.                                     @distributor_security_mode = @distributor_security_mode,
  11938.                                     @distributor_login = @distributor_login,
  11939.                                     @distributor_password = @distributor_password,
  11940.                                     @subscription_id = @subscription_id,
  11941.                                     @independent_agent = @independent_agent_id,
  11942.                                     @subscription_type = @subscription_type_id
  11943.  
  11944.  
  11945.             IF @@ERROR <> 0 or @retcode <> 0
  11946.                 BEGIN
  11947.                     if @@trancount > 0
  11948.                         ROLLBACK TRAN  addsubscription
  11949.                     RAISERROR (14057, 16, -1)
  11950.                     RETURN (1)
  11951.                 END
  11952.         END
  11953.     END
  11954.     COMMIT TRAN
  11955. go
  11956.  
  11957. EXEC dbo.sp_MS_marksystemobject sp_addsubscription
  11958. GO
  11959.  
  11960. print ''
  11961. print 'Creating procedure sp_MSchangeschemaarticle'
  11962. GO
  11963. CREATE PROCEDURE sp_MSchangeschemaarticle (
  11964.     @pubid int,
  11965.     @artid int,
  11966.     @property sysname,
  11967.     @value nvarchar(255)
  11968.     ) AS
  11969.     SET NOCOUNT ON
  11970.     DECLARE @retcode int
  11971.     DECLARE @pre_creation_cmdid tinyint
  11972.     DECLARE @statusid int
  11973.     DECLARE @schema_option_table_created bit
  11974.     DECLARE @creation_script nvarchar(255)
  11975.     DECLARE @type tinyint
  11976.     DECLARE @schema_option binary(8)
  11977.     DECLARE @valid_schema_options int
  11978.  
  11979.     SELECT @type = type 
  11980.       FROM sysextendedarticlesview
  11981.      WHERE artid = @artid
  11982.        AND pubid = @pubid 
  11983.  
  11984.     SELECT @schema_option_table_created = 0
  11985.  
  11986.     /* 
  11987.     ** The pubid and artid passed into this procedure from sp_changearticle
  11988.     ** have to be valid by now.
  11989.     */
  11990.     
  11991.     /*
  11992.     ** Parameter check: @property
  11993.     */
  11994.     SELECT @property = LOWER(@property collate SQL_Latin1_General_CP1_CS_AS)
  11995.     IF @property NOT IN ('description',
  11996.                          'dest_object',
  11997.                          'creation_script',
  11998.                          'pre_creation_cmd',
  11999.                          'schema_option',
  12000.                          'destination_owner')
  12001.     BEGIN
  12002.         RAISERROR(21224, 16, -1, @property)
  12003.         RETURN (1)
  12004.     END
  12005.                          
  12006.     -- Since all property changes will take the form of 
  12007.     -- simple update stataments, no transaction will be 
  12008.     -- started. 
  12009.  
  12010.     IF @property = N'description'
  12011.     BEGIN
  12012.         UPDATE sysschemaarticles 
  12013.            SET description = @value
  12014.          WHERE artid = @artid
  12015.            AND pubid = @pubid
  12016.  
  12017.         IF @@ERROR <> 0
  12018.             RETURN (1)
  12019.     END
  12020.     ELSE IF @property = N'dest_object'
  12021.     BEGIN
  12022.         UPDATE sysschemaarticles
  12023.            SET dest_object = @value
  12024.          WHERE artid = @artid
  12025.            AND pubid = @pubid 
  12026.  
  12027.         IF @@ERROR <> 0
  12028.             RETURN (1)
  12029.     END
  12030.     ELSE IF @property = N'creation_script'
  12031.     BEGIN
  12032.         UPDATE sysschemaarticles 
  12033.            SET creation_script = @value
  12034.          WHERE artid = @artid
  12035.            AND pubid = @pubid
  12036.  
  12037.         IF @@ERROR <> 0
  12038.             RETURN (1)
  12039.     END
  12040.     ELSE IF @property = N'pre_creation_cmd'
  12041.     BEGIN
  12042.         /* 
  12043.         ** Validate the given value for
  12044.         ** the property. It has to be either 
  12045.         ** 'none' or 'drop' case-insensitive.
  12046.         */
  12047.         SELECT @value = LOWER(@value collate SQL_Latin1_General_CP1_CS_AS)
  12048.         IF @value NOT IN ('none', 'drop')
  12049.         BEGIN
  12050.             RAISERROR(21223, 16, -1)
  12051.             RETURN (1)
  12052.         END
  12053.  
  12054.         IF @value = N'none'
  12055.             SELECT @pre_creation_cmdid = 0
  12056.         ELSE IF @value = N'drop'
  12057.             SELECT @pre_creation_cmdid = 1
  12058.         
  12059.         UPDATE sysschemaarticles
  12060.            SET pre_creation_cmd = @pre_creation_cmdid
  12061.          WHERE artid = @artid
  12062.            AND pubid = @pubid
  12063.         
  12064.         IF @@ERROR <> 0
  12065.             RETURN (1)
  12066.  
  12067.     END
  12068.     ELSE IF @property = N'schema_option'    
  12069.     BEGIN
  12070.         
  12071.         IF @value IS NULL
  12072.         BEGIN
  12073.             RAISERROR(14146, 16,1)
  12074.             RETURN (1)
  12075.         END
  12076.  
  12077.         CREATE TABLE #tab_changeschemaarticle (value varbinary(8) NULL)
  12078.         IF @@ERROR <> 0
  12079.         BEGIN
  12080.            RETURN (1)
  12081.         END
  12082.  
  12083.         EXEC ('insert #tab_changeschemaarticle values (' + 
  12084.             @value + ')')
  12085.  
  12086.         IF @@ERROR <> 0
  12087.         BEGIN
  12088.             DROP TABLE #tab_changeschemaarticle 
  12089.             RETURN (1)
  12090.         END
  12091.         
  12092.         SELECT @schema_option = fn_replprepadbinary8(value) 
  12093.           FROM #tab_changeschemaarticle
  12094.         /*
  12095.         ** schema_option can only contain the bits 0x0000000000000001 and
  12096.         ** 0x0000000000002000
  12097.         ** for schema only articles except view. View articles can contain 
  12098.         ** the options 0x0000000000000010, 0x0000000000000020, 
  12099.         ** and 0x0000000000000100 in addition to the aforementioned options.
  12100.         */
  12101.         IF @type = 0x40
  12102.         BEGIN
  12103.  
  12104.             -- Since only the lower 32 bits of @schema_option are
  12105.             -- currently used, the following check is sufficient.
  12106.             -- Note that @schema_option should have been padded by now.
  12107.             DECLARE @schema_option_lodword int
  12108.             SELECT @valid_schema_options = 0x2151
  12109.             SELECT @schema_option_lodword = fn_replgetbinary8lodword(@schema_option)
  12110.             IF (@schema_option_lodword & ~@valid_schema_options) <> 0
  12111.             BEGIN
  12112.                 RAISERROR (21229, 16, -1)
  12113.                 RETURN (1)
  12114.             END
  12115.         END
  12116.         ELSE IF @schema_option NOT IN (0x0000000000000000,
  12117.                                        0x0000000000000001,
  12118.                                        0x0000000000002000,
  12119.                                        0x0000000000002001)
  12120.         BEGIN
  12121.             DROP TABLE #tab_changeschemaarticle
  12122.             RAISERROR (21222, 16, -1)
  12123.             RETURN (1)
  12124.         END 
  12125.  
  12126.         IF EXISTS (SELECT * FROM #tab_changeschemaarticle
  12127.                     WHERE value = 0x0000000000000000)
  12128.         BEGIN
  12129.         
  12130.             SELECT @creation_script = NULL
  12131.             SELECT @creation_script = creation_script
  12132.               FROM sysschemaarticles
  12133.              WHERE artid = @artid
  12134.                AND pubid = @pubid
  12135. /*            
  12136.             IF @creation_script IS NULL OR
  12137.                @creation_script = N''
  12138.             BEGIN
  12139.                 RAISERROR(21218, 16, -1)
  12140.                 DROP TABLE #tab_changeschemaarticle
  12141.                 RETURN (1)
  12142.             END
  12143. */
  12144.         END
  12145.             
  12146.         UPDATE sysschemaarticles
  12147.            SET schema_option = tab.value
  12148.           FROM #tab_changeschemaarticle tab
  12149.          WHERE artid = @artid 
  12150.            AND pubid = @pubid         
  12151.             
  12152.         IF @@ERROR <> 0
  12153.         BEGIN
  12154.             DROP TABLE #tab_changeschemaarticle
  12155.             RETURN (1)
  12156.         END    
  12157.  
  12158.         DROP TABLE #tab_changeschemaarticle
  12159.  
  12160.         IF @@ERROR <> 0
  12161.             RETURN (1)
  12162.     END
  12163.     ELSE IF @property = N'destination_owner'
  12164.     BEGIN
  12165.         
  12166.         UPDATE sysschemaarticles
  12167.            SET dest_owner = @value
  12168.          WHERE artid = @artid
  12169.            AND pubid = @pubid
  12170.  
  12171.         IF @@ERROR <> 0
  12172.             RETURN (1)
  12173.     END    
  12174.  
  12175.     RAISERROR (14025, 10, -1)
  12176.     RETURN (0)
  12177. GO
  12178.  
  12179. EXEC dbo.sp_MS_marksystemobject sp_MSchangeschemaarticle
  12180. GO
  12181.  
  12182. print ''
  12183. print 'Creating procedure sp_changearticle'
  12184. GO
  12185. CREATE PROCEDURE sp_changearticle (
  12186.     @publication sysname = NULL,        /* Publication name */
  12187.     @article sysname = NULL,            /* Article name */
  12188.     @property nvarchar(20) = NULL,      /* The property to change */
  12189.     @value nvarchar(255) = NULL,        /* The new property value */
  12190.     @force_invalidate_snapshot bit = 0,    /* Force invalidate existing snapshot */
  12191.     @force_reinit_subscription bit = 0    /* Force reinit subscription */
  12192. ) AS
  12193. BEGIN
  12194.  
  12195.     SET NOCOUNT ON
  12196.  
  12197.     /*
  12198.     ** Declarations.
  12199.     */
  12200.  
  12201.     DECLARE @artid int
  12202.             ,@cmd1 nvarchar(512)
  12203.             ,@cmd2 nvarchar(512)
  12204.             ,@db sysname
  12205.             ,@filter int
  12206.             ,@object sysname
  12207.             ,@owner sysname
  12208.             ,@pubid int
  12209.             ,@retcode int
  12210.             ,@site sysname
  12211.             ,@sync_objid int
  12212.             ,@typeid tinyint
  12213.             ,@old_typeid tinyint
  12214.             ,@precmdid tinyint
  12215.             ,@active tinyint
  12216.             ,@virtual_id smallint
  12217.             ,@article_type tinyint
  12218.  
  12219.             ,@objid    int
  12220.             ,@objtype  nchar(2)
  12221.             ,@old_filter_name sysname
  12222.  
  12223.             ,@distributor sysname
  12224.             ,@distribdb sysname
  12225.             ,@dbname sysname
  12226.             ,@distproc nvarchar (255)
  12227.             ,@dts_part nvarchar(50)
  12228.             ,@no_dts_part nvarchar(50)
  12229.             ,@backward_comp_level int
  12230.             ,@allow_dts bit
  12231.             ,@allow_queued_tran bit
  12232.  
  12233.     select @backward_comp_level = 10 -- default to sphinx
  12234.             ,@dts_part = N'dts horizontal partitions'
  12235.             ,@no_dts_part = N'no dts horizontal partitions'
  12236.             ,@active = 2
  12237.             ,@virtual_id = -1
  12238.  
  12239.     /*
  12240.     ** Security Check
  12241.     */
  12242.     exec @retcode = dbo.sp_MSreplcheck_publish
  12243.     if @@ERROR <> 0 or @retcode <> 0
  12244.         return(1)
  12245.  
  12246.     /*
  12247.     ** Check to see if the database has been activated for publication.
  12248.     */
  12249.  
  12250.     IF (SELECT category & 1
  12251.           FROM master..sysdatabases
  12252.          WHERE name = DB_NAME() collate database_default) = 0
  12253.  
  12254.     BEGIN
  12255.             RAISERROR (14013, 16, -1)
  12256.             RETURN (1)
  12257.         END
  12258.  
  12259.  
  12260.     /*
  12261.     ** Parameter Check:  @publication.
  12262.     ** Make sure that the publication exists.
  12263.     */
  12264.  
  12265.     IF @publication IS NULL
  12266.         BEGIN
  12267.             RAISERROR (14043, 16, -1, '@publication')
  12268.             RETURN (1)
  12269.         END
  12270.  
  12271.     EXECUTE @retcode = dbo.sp_validname @publication
  12272.  
  12273.     IF @@ERROR <> 0 OR @retcode <> 0
  12274.     RETURN (1)
  12275.  
  12276.     SELECT @pubid = pubid
  12277.         ,@allow_dts = allow_dts
  12278.         ,@allow_queued_tran = allow_queued_tran
  12279.     FROM syspublications 
  12280.     WHERE name = @publication
  12281.  
  12282.     IF @pubid IS NULL
  12283.         BEGIN
  12284.             RAISERROR (20026, 11, -1, @publication)
  12285.             RETURN (1)
  12286.         END
  12287.  
  12288.     /*
  12289.     ** Check to see that the article exists in sysextendedarticlesview.
  12290.     ** Fetch the article identification number.
  12291.     */
  12292.  
  12293.     IF @article IS NULL
  12294.         BEGIN
  12295.             RAISERROR (14043, 16, -1, '@article')
  12296.             RETURN (1)
  12297.         END
  12298.  
  12299.     /*
  12300.     EXECUTE @retcode = dbo.sp_validname @article
  12301.  
  12302.     IF @retcode <> 0
  12303.     RETURN (1)
  12304.     */
  12305.     SELECT @artid = artid, @article_type = type, @objid = objid 
  12306.       FROM sysextendedarticlesview
  12307.      WHERE name = @article
  12308.        AND pubid = @pubid
  12309.     IF @artid IS NULL
  12310.         BEGIN
  12311.             RAISERROR (20027, 11, -1, @article)
  12312.             RETURN (1)
  12313.         END
  12314.  
  12315.  
  12316.     /*
  12317.     ** Get the object id and type from sysobjects
  12318.     */
  12319.  
  12320.     SELECT @objtype = type
  12321.        FROM sysobjects
  12322.        WHERE id = @objid
  12323.  
  12324.     IF @objtype IS NULL
  12325.     BEGIN
  12326.         RAISERROR( 20027, 11, -1, @article )
  12327.         RETURN( 1 )
  12328.     END
  12329.  
  12330.     /*
  12331.     ** Parameter Check:  @property.
  12332.     ** If the @property parameter is NULL, print the options.
  12333.     */
  12334.  
  12335.     IF @property IS NULL
  12336.         BEGIN
  12337.             CREATE TABLE #tab1 (properties sysname collate database_default not null)
  12338.             INSERT INTO #tab1 VALUES ('description')
  12339.             INSERT INTO #tab1 VALUES ('sync_object (log based article only)')
  12340.             INSERT INTO #tab1 VALUES ('type')
  12341.             INSERT INTO #tab1 VALUES ('ins_cmd (log based article only)')
  12342.             INSERT INTO #tab1 VALUES ('del_cmd (log based article only)')
  12343.             INSERT INTO #tab1 VALUES ('upd_cmd (log based article only)')
  12344.             INSERT INTO #tab1 VALUES ('filter (log based article only)')
  12345.             INSERT INTO #tab1 VALUES ('dest_table (log based article only)')
  12346.             INSERT INTO #tab1 VALUES ('dest_object')
  12347.             INSERT INTO #tab1 VALUES ('creation_script')
  12348.             INSERT INTO #tab1 VALUES ('pre_creation_cmd')
  12349.             INSERT INTO #tab1 VALUES ('status')
  12350.             INSERT INTO #tab1 VALUES ('schema_option')
  12351.             INSERT INTO #tab1 VALUES ('destination_owner')
  12352.                INSERT INTO #tab1 VALUES ('pub_identity_range (log based article only)')
  12353.             INSERT INTO #tab1 VALUES ('identity_range (log based article only)')
  12354.             INSERT INTO #tab1 VALUES ('threshold (log based article only)')
  12355.             PRINT ''
  12356.             SELECT * FROM #tab1
  12357.             RETURN (0)
  12358.         END
  12359.  
  12360.     /*
  12361.     ** At this point, we have completed all the validations and 
  12362.     ** preprocessings common to both regular and schema only articles 
  12363.     ** so we call a different proceudre here to handle the schema only
  12364.     ** articles differently.
  12365.     */
  12366.     
  12367.     IF @article_type in (0x20, 0x40, 0x80)
  12368.     BEGIN
  12369.         EXEC @retcode = sp_MSchangeschemaarticle 
  12370.                 @pubid = @pubid,
  12371.                 @artid = @artid,
  12372.                 @property = @property,
  12373.                 @value = @value    
  12374.         RETURN @retcode
  12375.     END  
  12376.  
  12377.     IF @objtype = 'U' AND LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) NOT IN 
  12378.                                                   ('description',
  12379.                                                    'sync_object',
  12380.                                                    'type',
  12381.                                                    'ins_cmd',
  12382.                                                    'del_cmd',
  12383.                                                    'upd_cmd',
  12384.                                                    'filter',
  12385.                                                    'dest_table',
  12386.                                                    'dest_object',
  12387.                                                    'creation_script',
  12388.                                                    'pre_creation_cmd',
  12389.                                                    'status',
  12390.                                                    'schema_option',
  12391.                                                    'destination_owner',
  12392.                                                     'pub_identity_range',
  12393.                                                     'identity_range',
  12394.                                                     'threshold')
  12395.         BEGIN
  12396.             RAISERROR (21183, 16, -1, @property)
  12397.             RETURN (1)
  12398.         END
  12399.  
  12400.     IF @objtype = 'P' AND LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) NOT IN 
  12401.                                                   ('description',
  12402.                                                    'dest_object',
  12403.                                                    'dest_table',
  12404.                                                    'creation_script',
  12405.                                                    'pre_creation_cmd',
  12406.                                                    'schema_option',
  12407.                                                    'destination_owner')
  12408.         BEGIN
  12409.             RAISERROR (14110, 16, -1)
  12410.             RETURN (1)
  12411.         END
  12412.  
  12413.  
  12414.     /* dest_object and 'dest_table' are same */
  12415.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'dest_object'
  12416.         SELECT @property = 'dest_table' 
  12417.  
  12418.     
  12419.     IF (@allow_dts = 1 or @allow_queued_tran = 1) and LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) IN ('ins_cmd', 'del_cmd', 'upd_cmd' )
  12420.     begin
  12421.         raiserror(21175, 16, -1)
  12422.         return (1)
  12423.     end
  12424.     
  12425.     /*
  12426.     ** Check to make sure that we have a valid type for status
  12427.     */
  12428.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'status'
  12429.     BEGIN
  12430.         IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) IN ('not owner qualified', 'owner qualified')
  12431.         BEGIN
  12432.             RAISERROR (21023, 16, -1,@value)
  12433.             RETURN (1)
  12434.         END
  12435.  
  12436.         IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('no column names', 'include column names', 'string literals', 'parameters',
  12437.             @dts_part, @no_dts_part )
  12438.         BEGIN
  12439.             RAISERROR (14097, 16, -1)
  12440.             RETURN (1)
  12441.         END
  12442.  
  12443.         IF    LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) in (@dts_part,@no_dts_part)
  12444.         begin
  12445.             if @allow_dts = 0
  12446.             begin
  12447.                 -- Invalid status for non dts pub
  12448.                 raiserror(20592, 16, -1)
  12449.                 RETURN (1)
  12450.             end
  12451.         end
  12452.         else
  12453.         begin
  12454.             if @allow_dts = 1
  12455.             begin
  12456.                 -- Invalid status for dts pub
  12457.                 raiserror(20591, 16, -1)
  12458.                 RETURN (1)
  12459.             end
  12460.         end
  12461.     end
  12462.     
  12463.     IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) IN ( 'ins_cmd', 'del_cmd', 'upd_cmd' )
  12464.     BEGIN
  12465.         if exists (select * from syspublications 
  12466.         where
  12467.         pubid = @pubid and sync_method = 3) and lower(@value) not like '%call%'
  12468.         BEGIN
  12469.             RAISERROR( 21154, 16, -1, @article )
  12470.             return 1
  12471.         END
  12472.     END
  12473.  
  12474.     declare @need_new_snapshot bit
  12475.         ,@need_reinit_subscription bit
  12476.  
  12477.     select @need_new_snapshot = 0
  12478.     select @need_reinit_subscription = 0
  12479.  
  12480.     if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) in ( N'ins_cmd', N'del_cmd', N'upd_cmd', 
  12481.         N'dest_table', N'destination_owner' ,N'type',N'filter',  
  12482.         N'pre_creation_cmd', N'schema_option') or 
  12483.         (LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'status' and LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) in (@dts_part,
  12484.         @no_dts_part))
  12485.     begin
  12486.         select @need_new_snapshot = 1
  12487.         select @need_reinit_subscription = 1
  12488.     end
  12489.     else if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) in ('sync_object',
  12490.         'creation_script')
  12491.     begin
  12492.         select @need_new_snapshot = 1
  12493.     end
  12494.  
  12495.     -- Have to call this stored procedure to invalidate existing snapshot or reint
  12496.     -- subscriptions if needed
  12497.     EXECUTE @retcode  = dbo.sp_MSreinit_article
  12498.         @publication = @publication, 
  12499.         @article = @article,
  12500.         @need_new_snapshot = @need_new_snapshot,
  12501.         @need_reinit_subscription = @need_reinit_subscription
  12502.         ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  12503.         ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  12504.         ,@check_only = 1
  12505.     IF @@ERROR <> 0 OR @retcode <> 0
  12506.         return(1)
  12507.  
  12508.     /*
  12509.     ** Change the property.
  12510.     */
  12511.  
  12512.     begin tran
  12513.     save TRAN sp_changearticle
  12514.  
  12515.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) IN ( 'description', 'ins_cmd', 'del_cmd', 'upd_cmd', 'dest_table', 'creation_script', 'dest_object')
  12516.             BEGIN
  12517.  
  12518.  
  12519.             /*
  12520.             ** Check the validity of the destination object.  NULL should
  12521.             ** get converted to the source object name.  Destination object
  12522.             ** names can be owner qualified, but not database qualified.
  12523.             */
  12524.  
  12525.             IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'dest_table' OR LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'dest_object'
  12526.                 BEGIN
  12527.                     IF @value IS NULL
  12528.                         SELECT @value = object_name(objid)
  12529.                           FROM sysarticles
  12530.                          WHERE artid = @artid
  12531.                            AND pubid = @pubid
  12532.                 END
  12533.  
  12534.             SELECT @cmd1 = 'UPDATE sysarticles '
  12535.  
  12536.             IF @value IS NULL
  12537.             BEGIN
  12538.                     SELECT @cmd1 = @cmd1 + '   SET ' + LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) + ' = NULL'
  12539.                 SELECT @cmd2 = ' WHERE artid = ' + STR(@artid)
  12540.                 SELECT @cmd2 = @cmd2 + '   AND pubid = ' + STR(@pubid)
  12541.                 EXECUTE (@cmd1 + @cmd2)
  12542.             END
  12543.             ELSE
  12544.             BEGIN
  12545.                 
  12546.                 SELECT @cmd1 = @cmd1 + '   SET ' + LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) + ' = ''' + @value + ''''
  12547.                 SELECT @cmd2 = ' WHERE artid = ' + STR(@artid)
  12548.                 SELECT @cmd2 = @cmd2 + '   AND pubid = ' + STR(@pubid)
  12549.                 EXECUTE (@cmd1 + @cmd2)
  12550.             END
  12551.  
  12552.             IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'upd_cmd'
  12553.             BEGIN
  12554.                 IF ( 0 <> ( SELECT PATINDEX( '%[789].[0-9]%', @@version ) ) ) OR
  12555.                    ( 0 <> ( SELECT PATINDEX( '%[1-9][0-9].[0-9]%', @@version ) ) )
  12556.                 BEGIN
  12557.                     exec dbo.sp_MSsetfilteredstatus @objid
  12558.                 END
  12559.  
  12560.             END
  12561.  
  12562.             IF @@ERROR <> 0 
  12563.                 BEGIN
  12564.                     if @@trancount > 0
  12565.                     begin
  12566.                         ROLLBACK TRAN sp_changearticle
  12567.                         commit tran
  12568.                     end
  12569.                     RETURN (1)
  12570.                 END
  12571.             END
  12572.  
  12573.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'sync_object'
  12574.             BEGIN
  12575.  
  12576.                 /*
  12577.                 ** Check for a valid synchronization object.
  12578.                 */
  12579.  
  12580.                 IF @value IS NULL
  12581.                     BEGIN
  12582.                         RAISERROR (14043, 16, -1, '@value')
  12583.                         if @@trancount > 0
  12584.                         begin
  12585.                             ROLLBACK TRAN sp_changearticle
  12586.                             commit tran
  12587.                         end
  12588.                         RETURN (1)
  12589.                     END
  12590.  
  12591.                 IF @value LIKE '%.%.%' OR @value LIKE '%.%'
  12592.                 BEGIN
  12593.                   select @object = PARSENAME( @value, 1 )
  12594.                   select @owner = PARSENAME(  @value, 2 )
  12595.                   select @db = PARSENAME(  @value, 3 )
  12596.                   select @site = PARSENAME(  @value, 4 )
  12597.  
  12598.                   if @object IS NULL
  12599.                         return 1
  12600.                 END
  12601.  
  12602.  
  12603.                 SELECT @sync_objid = OBJECT_ID(@value)
  12604.                 IF @sync_objid IS NULL
  12605.                     BEGIN
  12606.                         RAISERROR (15001, 11, -1, @value)
  12607.                         if @@trancount > 0
  12608.                         begin
  12609.                             ROLLBACK TRAN sp_changearticle
  12610.                             commit tran
  12611.                         end
  12612.                         RETURN (1)
  12613.                     END
  12614.  
  12615.                 IF NOT EXISTS (SELECT *
  12616.                                  FROM sysobjects
  12617.                                 WHERE type IN ('U', 'V')
  12618.                                   AND id = @sync_objid)
  12619.  
  12620.                     BEGIN
  12621.                         RAISERROR (14031, 16, -1)
  12622.                         if @@trancount > 0
  12623.                         begin
  12624.                             ROLLBACK TRAN sp_changearticle
  12625.                             commit tran
  12626.                         end
  12627.                         RETURN (1)
  12628.                     END
  12629.  
  12630.                 /*
  12631.                 ** Update the article with the new synchronization object.
  12632.                 */
  12633.  
  12634.                 UPDATE sysarticles
  12635.                    SET sync_objid = @sync_objid
  12636.                  WHERE artid = @artid
  12637.                    AND pubid = @pubid
  12638.  
  12639.                 IF @@ERROR <> 0 
  12640.                 BEGIN
  12641.                     if @@trancount > 0
  12642.                     begin
  12643.                         ROLLBACK TRAN sp_changearticle
  12644.                         commit tran
  12645.                     end
  12646.                     RETURN (1)
  12647.                 END
  12648.  
  12649.             END
  12650.  
  12651.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'type'
  12652.             BEGIN
  12653.  
  12654.                 /*
  12655.                 ** Check to make sure that we have a valid type.
  12656.                 */
  12657.  
  12658.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('logbased', 'logbased manualfilter', 'logbased manualview', 'logbased manualboth')
  12659.                     BEGIN
  12660.                         RAISERROR (14023, 16, -1)
  12661.                         if @@trancount > 0
  12662.                         begin
  12663.                             ROLLBACK TRAN sp_changearticle
  12664.                             commit tran
  12665.                         end
  12666.                         RETURN (1)
  12667.                     END
  12668.  
  12669.                 /*
  12670.                 ** Determine the integer value for the type.
  12671.                 */
  12672.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) IN ('logbased', 'indexed view logbased')
  12673.             SELECT @typeid = 1
  12674.             ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) IN ('logbased manualfilter', 'indexed view logbased manualfilter')
  12675.             SELECT @typeid = 3
  12676.             ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) IN ('logbased manualview', 'indexed view logbased manualview')
  12677.             SELECT @typeid = 5
  12678.             ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) IN ('logbased manualboth', 'indexed view logbased manualboth')
  12679.             SELECT @typeid = 7
  12680.  
  12681.                 /*
  12682.                 ** Update the article with the new type.
  12683.                 */
  12684.  
  12685.                 UPDATE sysarticles
  12686.                    SET type = @typeid
  12687.                  WHERE artid = @artid
  12688.                    AND pubid = @pubid
  12689.  
  12690.                 IF @@ERROR <> 0 
  12691.                 BEGIN
  12692.                     if @@trancount > 0
  12693.                     begin   
  12694.                         ROLLBACK TRAN sp_changearticle
  12695.                         commit tran
  12696.                     end
  12697.                     RETURN (1)
  12698.                 END
  12699.  
  12700.  
  12701.             END
  12702.  
  12703.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'filter'
  12704.             BEGIN
  12705.  
  12706.                 /*
  12707.                 ** Check for a valid filter value.
  12708.                 */
  12709.  
  12710.                 IF @value IS NOT NULL
  12711.                     BEGIN
  12712.  
  12713.                         IF @value LIKE '%.%.%' OR @value LIKE '%.%'
  12714.                         BEGIN
  12715.                            select @object = PARSENAME( @value, 1 )
  12716.                            select @owner = PARSENAME(  @value, 2 )
  12717.                            select @db = PARSENAME(  @value, 3 )
  12718.                            select @site = PARSENAME(  @value, 4 )
  12719.  
  12720.                            if @object IS NULL
  12721.                                  return 1
  12722.                         END
  12723.  
  12724.                     END
  12725.  
  12726.                 SELECT @filter = OBJECT_ID(@value)
  12727.  
  12728.                 IF @value IS NOT NULL
  12729.                     BEGIN
  12730.  
  12731.                         IF @filter IS NULL
  12732.                             BEGIN
  12733.                                 RAISERROR (15001, 11, -1, @value)
  12734.                                 if @@trancount > 0
  12735.                                 begin
  12736.                                     ROLLBACK TRAN sp_changearticle
  12737.                                     commit tran
  12738.                                 end
  12739.                                 RETURN (1)
  12740.                             END
  12741.  
  12742.                         IF NOT EXISTS (SELECT *
  12743.                                          FROM sysobjects
  12744.                                         WHERE type = 'RF'
  12745.                                           AND id = @filter)
  12746.  
  12747.                             BEGIN
  12748.                                 RAISERROR (14049, 16, -1)
  12749.                                 if @@trancount > 0
  12750.                                 begin
  12751.                                     ROLLBACK TRAN sp_changearticle
  12752.                                     commit tran
  12753.                                 end
  12754.                                 RETURN (1)
  12755.                             END
  12756.  
  12757.                     END
  12758.  
  12759.                 IF @value IS NULL SELECT @filter = 0
  12760.  
  12761.                 -----------------------------
  12762.                 -- save off the old filter
  12763.                 -----------------------------
  12764.  
  12765.                 SELECT @old_filter_name = object_name( filter )
  12766.                 FROM sysarticles WHERE artid = @artid
  12767.                 AND pubid = @pubid
  12768.  
  12769.                 IF @@ERROR <> 0 
  12770.                 BEGIN
  12771.                     if @@trancount > 0
  12772.                     begin
  12773.                         ROLLBACK TRAN sp_changearticle
  12774.                         commit tran
  12775.                     end
  12776.                     RETURN (1)
  12777.                 END
  12778.  
  12779.                 --------------------------------------------
  12780.                 -- Update the article with the new filter.
  12781.                 --------------------------------------------
  12782.  
  12783.                 UPDATE sysarticles
  12784.                    SET filter = @filter
  12785.                  WHERE artid = @artid
  12786.                    AND pubid = @pubid
  12787.  
  12788.                 IF @@ERROR <> 0 
  12789.                 BEGIN
  12790.                     if @@trancount > 0
  12791.                     begin
  12792.                         ROLLBACK TRAN sp_changearticle
  12793.                         commit tran
  12794.                     end
  12795.                     RETURN (1)
  12796.                 END
  12797.  
  12798.                 -- SQL SERVER > 7.x ONLY  disassociate old filter with table
  12799.                 -- and associate new one
  12800.  
  12801.                 IF ( 0 <> ( SELECT PATINDEX( '%[789].[0-9]%', @@version ) ) ) OR
  12802.                    ( 0 <> ( SELECT PATINDEX( '%[1-9][0-9].[0-9]%', @@version ) ) )   
  12803.                 BEGIN
  12804.  
  12805.                     ------------------------------------------
  12806.                     -- disassociate table from old filter proc
  12807.                     ------------------------------------------
  12808.  
  12809.                     EXEC dbo.sp_MSsetfilterparent @old_filter_name, 0
  12810.  
  12811.                     IF @@ERROR <> 0
  12812.                     BEGIN
  12813.                         if @@trancount > 0
  12814.                         begin
  12815.                             ROLLBACK TRAN sp_changearticle
  12816.                             commit tran
  12817.                         end
  12818.                         RETURN (1)
  12819.                     END
  12820.  
  12821.                     ------------------------------------------------------
  12822.                     -- set the parent of the filter proc to this object_id
  12823.                     ------------------------------------------------------
  12824.  
  12825.                     EXEC dbo.sp_MSsetfilterparent @value, @objid
  12826.  
  12827.                     IF @@ERROR <> 0
  12828.                     BEGIN
  12829.                         if @@trancount > 0
  12830.                         begin
  12831.                             ROLLBACK TRAN sp_changearticle
  12832.                             commit tran
  12833.                         end
  12834.                         RETURN (1)
  12835.                     END
  12836.                 END
  12837.  
  12838.             END
  12839.  
  12840.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'pre_creation_cmd'
  12841.             BEGIN
  12842.  
  12843.                 /*
  12844.                 ** Check to make sure that we have a valid pre_creation_cmd.
  12845.                 */
  12846.             IF @objtype = 'P' and LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('none', 'drop')
  12847.                 BEGIN
  12848.                     RAISERROR ( 14111, 16, -1 )
  12849.                     if @@trancount > 0
  12850.                     begin   
  12851.                         ROLLBACK TRAN sp_changearticle
  12852.                         commit tran
  12853.                     end
  12854.                     RETURN (1)
  12855.                 END
  12856.  
  12857.                 IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('none', 'drop', 'delete', 'truncate')
  12858.                     BEGIN
  12859.                         RAISERROR (14061, 16, -1)
  12860.                         if @@trancount > 0
  12861.                         begin
  12862.                             ROLLBACK TRAN sp_changearticle
  12863.                             commit tran
  12864.                         end
  12865.                         RETURN (1)
  12866.                     END
  12867.  
  12868.                 /*
  12869.                 ** Determine the integer value for the type.
  12870.                 */
  12871.  
  12872.                 IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'none'
  12873.                     SELECT @precmdid = 0
  12874.                 ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'drop'
  12875.                     SELECT @precmdid = 1
  12876.                 ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'delete'
  12877.                     SELECT @precmdid = 2
  12878.                 ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'truncate'
  12879.                     SELECT @precmdid = 3
  12880.  
  12881.                 /*
  12882.                 ** Update the article with the new pre_creation_cmd.
  12883.                 */
  12884.                 UPDATE sysarticles
  12885.                    SET pre_creation_cmd = @precmdid
  12886.                  WHERE artid = @artid
  12887.                    AND pubid = @pubid
  12888.  
  12889.                 IF @@ERROR <> 0 
  12890.                     BEGIN
  12891.                         if @@trancount > 0
  12892.                         begin
  12893.                             ROLLBACK TRAN sp_changearticle
  12894.                             commit tran
  12895.                         end
  12896.                         RETURN (1)
  12897.                     END
  12898.  
  12899.             END
  12900.  
  12901.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'status'
  12902.             BEGIN
  12903.                 /*
  12904.                 ** Determine the integer value for the type.
  12905.                 */
  12906.                 IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'not owner qualified'
  12907.                     UPDATE sysarticles 
  12908.                     SET status = status & ~4
  12909.                     WHERE artid = @artid
  12910.                                   AND pubid = @pubid
  12911.  
  12912.                 ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'owner qualified'
  12913.                     UPDATE sysarticles 
  12914.                     SET status = status | 4
  12915.                     WHERE artid = @artid
  12916.                                   AND pubid = @pubid
  12917.                      
  12918.                 ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'no column names'
  12919.                     UPDATE sysarticles 
  12920.                     SET status = status & ~8
  12921.                     WHERE artid = @artid
  12922.                                   AND pubid = @pubid
  12923.                      
  12924.                 ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'include column names'
  12925.                     UPDATE sysarticles 
  12926.                     SET status = status | 8
  12927.                     WHERE artid = @artid
  12928.                                   AND pubid = @pubid
  12929.  
  12930.                 ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'string literals'
  12931.                     UPDATE sysarticles 
  12932.                     SET status = status & ~16
  12933.                     WHERE artid = @artid
  12934.                                   AND pubid = @pubid
  12935.                      
  12936.                 ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'parameters'
  12937.                     UPDATE sysarticles 
  12938.                     SET status = status | 16
  12939.                     WHERE artid = @artid
  12940.                                   AND pubid = @pubid
  12941.                 ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = @dts_part
  12942.                 begin
  12943.                     if exists (select * from sysarticles where
  12944.                         artid = @artid and
  12945.                         status & 64 = 0)
  12946.                     begin
  12947.                         UPDATE sysarticles 
  12948.                             SET status = status | 64,
  12949.                                 upd_cmd = N'XCALL sp_MSXpd_' + @article
  12950.                             WHERE artid = @artid
  12951.                     end
  12952.                 end
  12953.                 ELSE IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = @no_dts_part
  12954.                 begin
  12955.                     if exists (select * from sysarticles where
  12956.                         artid = @artid and
  12957.                         status & 64 <> 0)
  12958.                     begin
  12959.                         UPDATE sysarticles 
  12960.                             SET status = status & ~64,
  12961.                                 upd_cmd = N'CALL sp_MSupd_' + @article
  12962.                             WHERE artid = @artid
  12963.                     end
  12964.                 end
  12965.                 IF @@ERROR <> 0 
  12966.                     BEGIN
  12967.                         if @@trancount > 0
  12968.                         begin
  12969.                             ROLLBACK TRAN sp_changearticle
  12970.                             commit tran
  12971.                         end
  12972.                         RETURN (1)
  12973.                     END
  12974.             END
  12975.  
  12976.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'schema_option'
  12977.             BEGIN
  12978.                 IF @value IS NULL
  12979.                     BEGIN
  12980.                         RAISERROR(14146, 16,1)
  12981.                         if @@trancount > 0
  12982.                         begin
  12983.                             ROLLBACK TRAN sp_changearticle
  12984.                             commit tran
  12985.                         end
  12986.                         RETURN (1)
  12987.                     END
  12988.  
  12989.                 CREATE TABLE #tab_changearticle (value varbinary(8) NULL)
  12990.                                      
  12991.                 IF @@ERROR <> 0 
  12992.                     BEGIN
  12993.                         if @@trancount > 0
  12994.                         begin
  12995.                             ROLLBACK TRAN sp_changearticle
  12996.                             commit tran
  12997.                         end
  12998.                         RETURN (1)
  12999.                     END
  13000.  
  13001.                 EXEC ('insert #tab_changearticle values (' + 
  13002.                         @value +')' )
  13003.                                      
  13004.                 IF @@ERROR <> 0 
  13005.                     BEGIN
  13006.                         if @@trancount > 0
  13007.                         begin
  13008.                             ROLLBACK TRAN sp_changearticle
  13009.                             commit tran
  13010.                         end
  13011.                         RETURN (1)
  13012.                     END
  13013.                 
  13014.                 IF @objtype = 'P' AND EXISTS (SELECT * from #tab_changearticle 
  13015.                     WHERE value <> 0x0000000000000000 AND
  13016.                           value <> 0x0000000000000001 )
  13017.                     BEGIN
  13018.                         RAISERROR ( 20014, 16, -1 )
  13019.                         if @@trancount > 0
  13020.                         begin
  13021.                             ROLLBACK TRAN sp_changearticle
  13022.                             commit tran
  13023.                         end
  13024.                         RETURN (1)
  13025.                     END
  13026.  
  13027.                 --
  13028.                 -- For queued updating publications
  13029.                 -- DRI option has to be included
  13030.                 --
  13031.                 if ((@allow_queued_tran = 1) and 
  13032.                     exists (select * from #tab_changearticle where 
  13033.                         fn_replgetbinary8lodword(fn_replprepadbinary8(value)) & 0x8000 = 0))
  13034.                 BEGIN
  13035.                     RAISERROR (21394, 16, 2)
  13036.                     if @@trancount > 0
  13037.                     begin
  13038.                         ROLLBACK TRAN sp_changearticle
  13039.                         commit tran
  13040.                     end
  13041.                     RETURN (1)
  13042.                 END
  13043.  
  13044.                 -- Seems to be a good place to check and see if using 
  13045.                 -- collation 0x00001000 or extended property 0x00002000
  13046.                 declare @schema_option_int int
  13047.                 select @schema_option_int  = 
  13048.                     fn_replgetbinary8lodword(fn_replprepadbinary8(value)) 
  13049.                 from #tab_changearticle
  13050.                 if ((@schema_option_int & 0x000001000 <> 0) or 
  13051.                     (@schema_option_int & 0x000002000 <> 0))
  13052.                 select @backward_comp_level = 40
  13053.                 -- End 
  13054.                
  13055.                 UPDATE sysarticles 
  13056.                    SET schema_option = fn_replprepadbinary8(tab.value) 
  13057.                   FROM #tab_changearticle tab 
  13058.                  WHERE artid = @artid
  13059.                    AND pubid = @pubid
  13060.                 DROP TABLE #tab_changearticle 
  13061.                                      
  13062.                 IF @@ERROR <> 0 
  13063.                     BEGIN
  13064.                         if @@trancount > 0
  13065.                         begin
  13066.                             ROLLBACK TRAN sp_changearticle
  13067.                             commit tran
  13068.                         end
  13069.                         RETURN (1)
  13070.                     END
  13071.  
  13072.             END
  13073.  
  13074.         IF LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'destination_owner'
  13075.             BEGIN
  13076.                 IF @value IS NOT NULL
  13077.                 BEGIN
  13078.                     EXECUTE @retcode = dbo.sp_validname @value
  13079.  
  13080.                     IF @retcode <> 0
  13081.                     BEGIN
  13082.                         if @@trancount > 0
  13083.                         begin
  13084.                             ROLLBACK TRAN sp_changearticle
  13085.                             commit tran
  13086.                         end
  13087.                         RETURN (1)
  13088.                     END
  13089.                 END
  13090.  
  13091.                 UPDATE sysarticles SET dest_owner = @value from 
  13092.                     sysarticles WHERE artid = @artid
  13093.                                   AND pubid = @pubid
  13094.                                      
  13095.                 IF @@ERROR <> 0 
  13096.                     BEGIN
  13097.                         if @@trancount > 0
  13098.                         begin
  13099.                             ROLLBACK TRAN sp_changearticle
  13100.                             commit tran
  13101.                         end
  13102.                         RETURN (1)
  13103.                     END
  13104.  
  13105.             END
  13106.  
  13107.            
  13108.         if  LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'pub_identity_range'
  13109.         begin
  13110.             if not exists (select * from sysarticleupdates where artid = @artid and
  13111.                 identity_support = 1)
  13112.             begin
  13113.                 raiserror(21235, 16, -1, @property)
  13114.                 goto UNDO
  13115.             end
  13116.  
  13117.             declare @pub_range bigint
  13118.             select @pub_range = convert(bigint, @value) 
  13119.             if @pub_range < 0
  13120.             begin
  13121.                 raiserror(21232, 16, -1)
  13122.                 goto UNDO
  13123.             end
  13124.  
  13125.             if exists (select * from MSpub_identity_range where objid = @objid and
  13126.                 pub_range < 0)
  13127.                 select @pub_range = @pub_range * -1
  13128.             
  13129.             update MSpub_identity_range set
  13130.                 pub_range = @pub_range 
  13131.                 where objid=@objid
  13132.             if @@error < 0
  13133.                 goto UNDO
  13134.         end
  13135.                 
  13136.         if  LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'identity_range'
  13137.         begin
  13138.             if not exists (select * from sysarticleupdates where artid = @artid and
  13139.                 identity_support = 1)
  13140.             begin
  13141.                 raiserror(21235, 16, -1, @property)
  13142.                 goto UNDO
  13143.             end
  13144.  
  13145.             declare @range bigint
  13146.             select @range = convert(bigint, @value) 
  13147.             if @range < 0
  13148.             begin
  13149.                 raiserror(21232, 16, -1)
  13150.                 goto UNDO
  13151.             end
  13152.  
  13153.             if exists (select * from MSpub_identity_range where objid = @objid and
  13154.                 range < 0)
  13155.                 select @range = @range * -1
  13156.             
  13157.             update MSpub_identity_range set
  13158.                 range = @range 
  13159.                 where objid=@objid
  13160.             if @@error < 0
  13161.                 goto UNDO
  13162.  
  13163.             -- Distributor side data will be changed later by sp_MSchange_article.
  13164.         end
  13165.  
  13166.         -- Check to see if the range is too big.
  13167.         -- Must be down after the change. If the check fails, the transaction
  13168.         -- will be rolled back.
  13169.         if  LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) in ('pub_identity_range', 'identity_range')
  13170.         begin
  13171.             declare @pub_identity_range bigint, @identity_range int
  13172.             select @pub_identity_range = pub_range, 
  13173.                 @identity_range = range from MSpub_identity_range where
  13174.                 objid = @objid 
  13175.  
  13176.             declare @xtype int, @xprec int, @max_range bigint
  13177.             select @xtype=xtype, @xprec=xprec from syscolumns where id=@objid and 
  13178.                 columnproperty(id, name, 'IsIdentity')=1
  13179.             select @max_range =
  13180.                     case @xtype when 52 then power((convert(bigint,2)), 8*2-1) - 1 --smallint 
  13181.                         when 48 then power((convert(bigint,2)), 8-1) - 1          --tinyint
  13182.                         when 56 then power((convert(bigint,2)), 8*4-1) - 1          --int
  13183.                         when 127 then power((convert(bigint,2)), 62) - 1 + power((convert(bigint,2)), 62)      --bigint
  13184.                            when 108 then power((convert(bigint,10)), @xprec)      --numeric
  13185.                            when 106 then power((convert(bigint,10)), @xprec)      --decimal
  13186.                      else
  13187.                         power((convert(bigint,2)), 62) + power((convert(bigint,2)), 62) - 1  -- defaulted to bigint
  13188.                     end
  13189.         
  13190.             declare @source_table nvarchar (386)
  13191.             exec @retcode = dbo.sp_MSget_qualified_name @objid, @source_table output
  13192.             if @retcode <> 0 or @@error <> 0
  13193.                 goto UNDO
  13194.             if @pub_identity_range * 2 + @identity_range > (@max_range - IDENT_CURRENT(@source_table))
  13195.                 begin
  13196.                     raiserror(21290, 16, -1)
  13197.                     goto UNDO
  13198.                 end
  13199.         end
  13200.  
  13201.         if  LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) = 'threshold'
  13202.         begin
  13203.             if not exists (select * from sysarticleupdates where artid = @artid and
  13204.                 identity_support = 1)
  13205.             begin
  13206.                 raiserror(21235, 16, -1, @property)
  13207.                 goto UNDO
  13208.             end
  13209.  
  13210.             declare @threshold bigint
  13211.             select @threshold = convert(int, @value) 
  13212.             if @threshold < 1 or @threshold > 100
  13213.             begin
  13214.                 raiserror(21233, 16, -1)
  13215.                 goto UNDO
  13216.             end
  13217.  
  13218.             update MSpub_identity_range set
  13219.                 threshold = @threshold
  13220.                 where objid=@objid
  13221.             if @@error < 0
  13222.                 goto UNDO
  13223.             -- Distributor side data will be changed later by sp_MSchange_article.
  13224.         end
  13225.  
  13226.         -------------------------------------------------------------------------
  13227.         -- some info on articles is also stored at the distributor.
  13228.         -- update info at distributor if these properties change
  13229.         -------------------------------------------------------------------------
  13230.  
  13231.         if LOWER(@property collate SQL_Latin1_General_CP1_CS_AS) in ( N'description', N'dest_table', N'dest_object', 
  13232.             'identity_range', 'threshold' )
  13233.         BEGIN
  13234.             /*
  13235.             ** Get distribution server information for remote RPC call.
  13236.             */
  13237.             EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  13238.                @distribdb   = @distribdb OUTPUT
  13239.             IF @@ERROR <> 0 or @retcode <> 0
  13240.             BEGIN
  13241.                 RAISERROR (14071, 16, -1)
  13242.                 if @@trancount > 0
  13243.                 begin
  13244.                     ROLLBACK TRAN sp_changearticle
  13245.                     commit tran
  13246.                 end
  13247.                 RETURN (1)
  13248.             END
  13249.  
  13250.             SELECT @dbname =  DB_NAME()
  13251.  
  13252.             SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  13253.                 '.dbo.sp_MSchange_article'
  13254.             EXECUTE @retcode = @distproc
  13255.                 @publisher = @@SERVERNAME,
  13256.                 @publisher_db = @dbname,
  13257.                 @publication = @publication,
  13258.                 @article = @article,
  13259.                 @article_id = @artid,
  13260.                 @property = @property,
  13261.                 @value = @value
  13262.  
  13263.  
  13264.             IF @@ERROR <> 0 OR @retcode <> 0
  13265.             BEGIN
  13266.                 if @@trancount > 0
  13267.                 begin
  13268.                     ROLLBACK TRAN sp_changearticle
  13269.                     commit tran
  13270.                 end
  13271.                 RETURN (1)
  13272.             END
  13273.         END
  13274.  
  13275.         -- Have to call this stored procedure to invalidate existing snapshot or reint
  13276.         -- subscriptions if needed
  13277.         EXECUTE @retcode  = dbo.sp_MSreinit_article
  13278.             @publication = @publication, 
  13279.             @article = @article,
  13280.             @need_new_snapshot = @need_new_snapshot,
  13281.             @need_reinit_subscription = @need_reinit_subscription
  13282.             ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  13283.             ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  13284.         IF @@ERROR <> 0 OR @retcode <> 0
  13285.             GOTO UNDO
  13286.  
  13287.  
  13288. if @backward_comp_level > 10
  13289.     update syspublications set backward_comp_level = @backward_comp_level where pubid = @pubid
  13290.     COMMIT TRAN
  13291.  
  13292.     /*
  13293.     ** Force the article cache to be refreshed with the new definition.
  13294.     */
  13295.     EXECUTE dbo.sp_replflush
  13296.  
  13297.     /*
  13298.     ** Return succeed.
  13299.     */
  13300.  
  13301.     RAISERROR (14025, 10, -1)
  13302.     RETURN (0)
  13303.  
  13304. UNDO:
  13305.     if @@TRANCOUNT > 0
  13306.     begin
  13307.         ROLLBACK TRAN sp_changearticle
  13308.         COMMIT TRAN
  13309.     end
  13310.     return(1)
  13311. END
  13312. go
  13313.  
  13314. dump tran master with no_log
  13315. go
  13316.  
  13317. EXEC dbo.sp_MS_marksystemobject sp_changearticle
  13318. GO
  13319.  
  13320. print ''
  13321. print 'Creating procedure sp_droparticle'
  13322. go
  13323.  
  13324. CREATE PROCEDURE sp_droparticle(
  13325.     @publication sysname,     /* The publication name */
  13326.     @article sysname,          /* The article name */
  13327.     @ignore_distributor bit = 0,    
  13328.     @force_invalidate_snapshot bit = 0    /* Force invalidate existing snapshot */
  13329.  
  13330. AS
  13331. BEGIN
  13332.     /*
  13333.     ** Declarations.
  13334.     */
  13335.  
  13336.     DECLARE @cmd nvarchar(255)
  13337.     DECLARE @objid int
  13338.     DECLARE @pubid int
  13339.     DECLARE @publish_bit smallint
  13340.     DECLARE @retcode int
  13341.     DECLARE @filter_name sysname
  13342.     DECLARE @view_name sysname
  13343.     DECLARE @type tinyint
  13344.     DECLARE @procnum smallint
  13345.     DECLARE @virtual_id smallint
  13346.     DECLARE @push tinyint
  13347.     DECLARE @distributor sysname
  13348.     DECLARE @distribdb sysname
  13349.     DECLARE @distproc nvarchar (255)
  13350.     DECLARE @dbname sysname
  13351.     -- SyncTran
  13352.     DECLARE @allow_sync_tran_id bit
  13353.     DECLARE @allow_queued_tran_id bit
  13354.     declare @artid int, @insproc_id int, @updproc_id int, @delproc_id int, @updtrig_id int
  13355.     declare @filter_id int
  13356.     declare @view_id int
  13357.     declare @tran_conflict_tabid int
  13358.     declare @tran_conflict_procid int
  13359.  
  13360.     SET NOCOUNT ON
  13361.  
  13362.     /*
  13363.     ** Initializations.
  13364.     */
  13365.  
  13366.     SELECT @virtual_id = -1     /* Const: virtual subscriber id */
  13367.     SELECT @publish_bit = 1
  13368.  
  13369.  
  13370.     /*
  13371.     ** Security Check.
  13372.     */
  13373.     exec @retcode = dbo.sp_MSreplcheck_publish
  13374.     if @@ERROR <> 0 or @retcode <> 0
  13375.         return(1)
  13376.  
  13377.     /*
  13378.     ** Parameter Check: @publication.
  13379.     ** The @publication name must conform to the rules for identifiers.
  13380.     */
  13381.  
  13382.     IF @publication IS NULL
  13383.         BEGIN
  13384.             RAISERROR (14043, 16, -1, '@publication')
  13385.             RETURN (1)
  13386.         END
  13387.  
  13388.     EXECUTE @retcode = dbo.sp_validname @publication
  13389.  
  13390.     IF @retcode <> 0
  13391.     RETURN (1)
  13392.  
  13393.     IF NOT EXISTS (SELECT * FROM syspublications WHERE name = @publication)
  13394.         BEGIN
  13395.             RAISERROR (20026, 11, -1, @publication)
  13396.             RETURN (1)
  13397.         END
  13398.  
  13399.  
  13400.     /*
  13401.     ** Get the @pubid.
  13402.     */
  13403.  
  13404.     -- SyncTran
  13405.     --SELECT @pubid = pubid FROM syspublications WHERE name = @publication
  13406.     SELECT @pubid = pubid, @allow_sync_tran_id = allow_sync_tran,
  13407.         @allow_queued_tran_id = allow_queued_tran
  13408.     FROM syspublications WHERE name = @publication
  13409.  
  13410.     /*
  13411.     ** Parameter Check:  @article.
  13412.     ** If the @article is 'all', drop all articles for the specified
  13413.     ** publication (@publication).
  13414.     */
  13415.  
  13416.     IF LOWER(@article) = 'all'
  13417.         BEGIN
  13418.             -- If drop all articles, set force flag to true
  13419.             select @force_invalidate_snapshot = 1
  13420.             DECLARE hC  CURSOR LOCAL FAST_FORWARD FOR 
  13421.                 SELECT DISTINCT  name FROM sysextendedarticlesview 
  13422.                     WHERE pubid = @pubid
  13423.             OPEN hC
  13424.             FETCH hC INTO @article
  13425.             WHILE (@@fetch_status <> -1)
  13426.                 BEGIN
  13427.                     EXECUTE dbo.sp_droparticle 
  13428.                         @publication = @publication, 
  13429.                         @article = @article,
  13430.                         @ignore_distributor = @ignore_distributor,
  13431.                         @force_invalidate_snapshot = @force_invalidate_snapshot
  13432.  
  13433.                     FETCH hC INTO @article
  13434.                 END
  13435.             CLOSE hC
  13436.             DEALLOCATE hC
  13437.             RETURN (0)
  13438.         END
  13439.  
  13440.     /*
  13441.     ** Parameter Check: @article.
  13442.     ** The @article name must conform to the rules for identifiers.
  13443.     */
  13444.  
  13445.     IF @article IS NULL
  13446.         BEGIN
  13447.             RAISERROR (14043, 16, -1, '@article')
  13448.             RETURN (1)
  13449.         END
  13450.  
  13451.     /*
  13452.     EXECUTE @retcode = dbo.sp_validname @article
  13453.  
  13454.     IF @retcode <> 0
  13455.     RETURN (1)
  13456.     */
  13457.  
  13458.     /*
  13459.     ** Ascertain the existence of the article.
  13460.     */
  13461.  
  13462.     IF NOT EXISTS (SELECT *
  13463.                      FROM sysextendedarticlesview
  13464.                     WHERE name = @article
  13465.                       AND pubid = @pubid)
  13466.         BEGIN
  13467.             RAISERROR (20027, 11, -1, @article)
  13468.         RETURN (1)
  13469.         END
  13470.  
  13471.     /*
  13472.     ** Check to make sure that there are no 'real' subscriptions on the article.
  13473.     */
  13474.  
  13475.     IF EXISTS (SELECT *
  13476.                  FROM syssubscriptions, sysextendedarticlesview
  13477.                 WHERE sysextendedarticlesview.name = @article
  13478.                   AND sysextendedarticlesview.pubid = @pubid
  13479.                   AND sysextendedarticlesview.artid = syssubscriptions.artid
  13480.                   AND syssubscriptions.srvid <> @virtual_id)
  13481.         BEGIN
  13482.             RAISERROR (14046, 16, -1)
  13483.             RETURN (1)
  13484.         END
  13485.  
  13486.     -- 
  13487.     -- If SyncTran/QueuedTran enabled
  13488.     -- retrieve info from sysarticle updates
  13489.     --
  13490.     if (@allow_sync_tran_id = 1 or @allow_queued_tran_id = 1)
  13491.     begin
  13492.         select @artid = artid from sysarticles where name = @article and pubid = @pubid
  13493.         select @insproc_id = sync_ins_proc, @updproc_id = sync_upd_proc, @delproc_id = sync_del_proc,
  13494.             @updtrig_id = sync_upd_trig,
  13495.             @tran_conflict_tabid = conflict_tableid,
  13496.             @tran_conflict_procid = ins_conflict_proc
  13497.         from sysarticleupdates
  13498.         where artid = @artid and pubid = @pubid 
  13499.     end
  13500.     -- end SyncTran
  13501.  
  13502.     /*
  13503.     ** Retrieve the object id of the underlying object,
  13504.     ** article id, and article type. Note that the 
  13505.     ** subsequent code relies on the values of the variables in
  13506.     ** the select list. Please do not remove any variable from 
  13507.     ** the seletc list unless you make sure that all the subsequent
  13508.     ** references to the variable are accounted for.  
  13509.     */
  13510.  
  13511.     SELECT @artid = artid, @objid = objid, @type = type
  13512.       FROM sysextendedarticlesview
  13513.      WHERE name = @article
  13514.        AND pubid = @pubid
  13515.  
  13516.     begin tran
  13517.     save TRAN droparticle
  13518.  
  13519.         -- @ignore_distributor is set to 1 when removing replication forcefully. In that
  13520.         -- case, no need to check or reinit
  13521.         if @ignore_distributor = 0
  13522.         begin
  13523.             -- Have to call this stored procedure to invalidate existing snapshot
  13524.             -- if there are any. immediate_sync_ready bit would be changed or error will be railsed.
  13525.             EXECUTE @retcode  = dbo.sp_MSreinit_article
  13526.                 @publication = @publication, 
  13527.                 @need_new_snapshot = 1,
  13528.                 @force_invalidate_snapshot = @force_invalidate_snapshot
  13529.             IF @@ERROR <> 0 OR @retcode <> 0
  13530.                 GOTO UNDO
  13531.         end
  13532.  
  13533.         /* Drop virtual subscription first for @immediate_sync publications
  13534.          */
  13535.         if EXISTS (SELECT * FROM syspublications WHERE
  13536.             name = @publication    AND
  13537.             immediate_sync = 1)
  13538.         BEGIN
  13539.             EXECUTE @retcode  = dbo.sp_dropsubscription 
  13540.                 @publication = @publication, 
  13541.                 @article = @article,
  13542.                 @subscriber = NULL,
  13543.                 @ignore_distributor = @ignore_distributor,
  13544.                 @reserved = 'internal'
  13545.             IF @@ERROR <> 0 OR @retcode <> 0
  13546.             BEGIN
  13547.                 if @@trancount > 0
  13548.                 begin
  13549.                     ROLLBACK TRAN droparticle
  13550.                     commit tran
  13551.                 end
  13552.                 RETURN (1)
  13553.             END
  13554.         END
  13555.  
  13556.         /* Drop article at the distributor side */
  13557.         /*
  13558.         ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
  13559.         */
  13560.         if @ignore_distributor = 0
  13561.         begin
  13562.  
  13563.             /*
  13564.             ** Get distribution server information for remote RPC call.
  13565.             */
  13566.             EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  13567.                @distribdb   = @distribdb OUTPUT
  13568.             IF @@ERROR <> 0 or @retcode <> 0
  13569.                 BEGIN
  13570.                     RETURN (1)
  13571.                 END
  13572.  
  13573.             SELECT @dbname =  DB_NAME()
  13574.         
  13575.             SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  13576.                 '.dbo.sp_MSdrop_article'
  13577.             EXECUTE @retcode = @distproc
  13578.                 @publisher = @@SERVERNAME,
  13579.                 @publisher_db = @dbname,
  13580.                 @publication = @publication,
  13581.                 @article = @article
  13582.  
  13583.             IF @@ERROR <> 0 OR @retcode <> 0
  13584.             BEGIN
  13585.                 if @@trancount > 0
  13586.                     ROLLBACK TRAN 
  13587.                 RETURN (1)
  13588.             END
  13589.         end
  13590.  
  13591.         IF @type IN (0x20, 0x40, 0x80)
  13592.         BEGIN
  13593.             -- Handle the schema only articles a little bit differently from 
  13594.             -- other articles as they are simpler objects. 
  13595.  
  13596.             -- Note that we have already obtained the article id earlier 
  13597.             -- so we can use that to delete the corresponding record
  13598.             -- in sysschemaarticles
  13599.             
  13600.             DELETE sysschemaarticles WHERE artid = @artid and pubid = @pubid
  13601.  
  13602.             -- If the object is no longer published as an schema only
  13603.             -- article, unmark its published for schema only bit (512) in 
  13604.             -- sysobjects/replinfo so that it can be dropped by the user.
  13605.             -- Note that we need to check sysmergeschemaarticles too.
  13606.  
  13607.  
  13608.             -- Note that we have obtained the object id for the undelying 
  13609.             -- object of this article already.
  13610.  
  13611.             IF NOT EXISTS (SELECT * 
  13612.                              FROM sysschemaarticles 
  13613.                             WHERE objid = @objid)
  13614.             BEGIN
  13615.                 SELECT @publish_bit = 512
  13616.                 IF NOT EXISTS (SELECT * 
  13617.                                  FROM sysobjects 
  13618.                                 WHERE name = 'sysmergeschemaarticles')
  13619.                 BEGIN
  13620.                     UPDATE sysobjects 
  13621.                        SET replinfo = replinfo & ~@publish_bit
  13622.                     WHERE id = @objid 
  13623.                 END
  13624.                 ELSE IF NOT EXISTS (SELECT * 
  13625.                                       FROM sysmergeschemaarticles
  13626.                                      WHERE objid = @objid)
  13627.                 BEGIN
  13628.                     UPDATE sysobjects 
  13629.                        SET replinfo = replinfo & ~@publish_bit
  13630.                     WHERE id = @objid 
  13631.                 END
  13632.             END  
  13633.         END
  13634.         ELSE
  13635.         BEGIN
  13636.         
  13637.             /*
  13638.             **  Delete article from sysarticles and clear publish bit in
  13639.             **  sysobjects.
  13640.             */
  13641.  
  13642.  
  13643.             /*
  13644.             ** If this article is the only one that references this object,
  13645.             ** then we can safely turn off the publish bit in sysobjects.
  13646.             */
  13647.  
  13648.             IF NOT EXISTS (SELECT *
  13649.                              FROM sysarticles
  13650.                             WHERE objid = @objid
  13651.                               AND NOT (name = @article AND pubid = @pubid))
  13652.                 BEGIN
  13653.  
  13654.                 UPDATE sysobjects SET replinfo = replinfo & ~ @publish_bit 
  13655.                     WHERE id = (SELECT objid FROM sysarticles WHERE name = @article 
  13656.                         AND pubid =  @pubid) 
  13657.  
  13658.                 /*
  13659.                 EXEC (@cmd)
  13660.  
  13661.                 IF @@ERROR <> 0
  13662.                     BEGIN
  13663.                         if @@trancount > 0
  13664.                             ROLLBACK TRAN
  13665.                         RAISERROR (14047, 16, -1, @article)
  13666.                         RETURN (1)
  13667.                     END
  13668.                 */
  13669.  
  13670.                 END
  13671.  
  13672.             /*
  13673.             ** Drop article view if not logbased manualview (type = 5)
  13674.             */
  13675.             IF (@type & 5) = 1
  13676.             BEGIN    
  13677.                 SELECT @view_id = sysobjects.id
  13678.                   FROM sysarticles, sysobjects
  13679.                  WHERE sysarticles.name = @article
  13680.                    AND pubid = @pubid
  13681.                    AND sync_objid = sysobjects.id
  13682.                    AND sysobjects.type = 'V'
  13683.                 exec sp_MSget_qualified_name @view_id, @view_name OUTPUT
  13684.  
  13685.             END
  13686.  
  13687.             /*
  13688.             ** Drop article filter if not logbased manualfilter (type = 3)
  13689.             */
  13690.             IF (@type & 3) = 1
  13691.             BEGIN    
  13692.                 SELECT @filter_id = sysobjects.id
  13693.                   FROM sysarticles, sysobjects
  13694.                  WHERE sysarticles.name = @article
  13695.                    AND pubid = @pubid
  13696.                    AND filter = sysobjects.id
  13697.                    AND sysobjects.type = 'RF'
  13698.  
  13699.                 exec sp_MSget_qualified_name @filter_id, @filter_name OUTPUT
  13700.        
  13701.             END
  13702.  
  13703.  
  13704.             IF( @type & 3 ) = 3
  13705.             BEGIN
  13706.                 select @filter_id =  filter from sysarticles
  13707.                 where name = @article and pubid = @pubid
  13708.  
  13709.                 exec sp_MSget_qualified_name @filter_id, @filter_name OUTPUT
  13710.  
  13711.                 if @filter_name is not null
  13712.                     EXEC dbo.sp_MSsetfilterparent @filter_name, 0
  13713.             
  13714.                 -- Clear base table dependency on the filter
  13715.                 EXEC dbo.sp_MSsetfilteredstatus @objid
  13716.  
  13717.                 -- This is a manual filter, we should not drop it automatically
  13718.                 -- since it is not created by us.
  13719.                 -- Set @filter_id to null so the object will not be dropped later.
  13720.                 select @filter_name = null
  13721.  
  13722.             END
  13723.  
  13724.  
  13725.             /*
  13726.             ** If this is a table based article, Drop all article columns.
  13727.             ** This is done to force all Text\Image column status to be updated.
  13728.             */
  13729.  
  13730.             IF (@type & 8) != 8
  13731.             BEGIN
  13732.  
  13733.                 -- propagate @ignore_distributor to sp_articlecolumn to allow forced cleanup
  13734.                 EXECUTE @retcode  = dbo.sp_articlecolumn @publication, @article,
  13735.                 @operation = 'drop', @ignore_distributor = @ignore_distributor
  13736.                 -- synctran
  13737.                 , @refresh_synctran_procs = 0
  13738.                 , @force_invalidate_snapshot = @force_invalidate_snapshot
  13739.                 IF @@ERROR <> 0 OR @retcode <> 0
  13740.                 BEGIN
  13741.                     if @@trancount > 0
  13742.                     begin
  13743.                         ROLLBACK TRAN droparticle
  13744.                         commit tran
  13745.                     end
  13746.                     RETURN (1)
  13747.                 END
  13748.             END
  13749.  
  13750.  
  13751.             /*
  13752.             ** Remove the row from sysarticles.
  13753.             */
  13754.             DELETE
  13755.               FROM sysarticles
  13756.              WHERE name = @article
  13757.                AND pubid = @pubid
  13758.  
  13759.             IF @@ERROR <> 0
  13760.             BEGIN
  13761.                 if @@trancount > 0
  13762.                     ROLLBACK TRAN 
  13763.                 RAISERROR (14047, 16, -1, @article)
  13764.                 RETURN (1)
  13765.             END
  13766.  
  13767.             -- SyncTran
  13768.             /*
  13769.             ** Drop associated sync tran procs and entries in sysarticle updates
  13770.             */
  13771.             if (@allow_sync_tran_id = 1 or @allow_queued_tran_id = 1)
  13772.             begin
  13773.                 exec @retcode = dbo.sp_MSdrop_object 
  13774.                     @object_id = @insproc_id
  13775.                 if @retcode <> 0 or @@error <> 0
  13776.                     goto UNDO
  13777.  
  13778.                 exec @retcode = dbo.sp_MSdrop_object 
  13779.                     @object_id = @updproc_id
  13780.                 if @retcode <> 0 or @@error <> 0
  13781.                     goto UNDO
  13782.  
  13783.                 exec @retcode = dbo.sp_MSdrop_object 
  13784.                     @object_id = @delproc_id
  13785.                 if @retcode <> 0 or @@error <> 0
  13786.                     goto UNDO
  13787.             
  13788.                 if @updtrig_id is not null
  13789.                 begin
  13790.                     exec @retcode = dbo.sp_MSdrop_object 
  13791.                         @object_id = @updtrig_id
  13792.                     if @retcode <> 0 or @@error <> 0
  13793.                         goto UNDO
  13794.                 end
  13795.  
  13796.                 -- drop conflict tables as necessary
  13797.                 if @tran_conflict_tabid is not null
  13798.                 begin
  13799.                     exec @retcode = dbo.sp_MSdrop_object 
  13800.                         @object_id = @tran_conflict_tabid
  13801.                     if @retcode <> 0 or @@error <> 0
  13802.                         goto UNDO
  13803.                 end
  13804.  
  13805.                 if @tran_conflict_procid is not null
  13806.                 begin
  13807.                     exec @retcode = dbo.sp_MSdrop_object 
  13808.                         @object_id = @tran_conflict_procid
  13809.                     if @retcode <> 0 or @@error <> 0
  13810.                         goto UNDO
  13811.                 end
  13812.  
  13813.                 delete from sysarticleupdates where artid = @artid and pubid = @pubid
  13814.                 if @@ERROR <> 0 
  13815.                 begin
  13816.                     if @@trancount > 0
  13817.                         ROLLBACK TRAN
  13818.                     RETURN (1)
  13819.  
  13820.                 end
  13821.  
  13822.                 -- Cleanup MSpub_identity_range if needed.
  13823.                 if not exists (select * from sysarticles where objid = @objid)
  13824.                 begin
  13825.                     if exists (select * from MSpub_identity_range where objid = @objid)
  13826.                     begin
  13827.                         -- Drop the identity range constraits.
  13828.                         -- RESEED and change constraint
  13829.                         exec @retcode = dbo.sp_MSreseed
  13830.                             @objid =  @objid,
  13831.                             -- next_seed and range can be anything.
  13832.                             @next_seed = 10,
  13833.                             @range = 10,
  13834.                             @is_publisher = -1,
  13835.                             @check_only = 1,
  13836.                             @drop_only = 1
  13837.                         IF @retcode <> 0 or @@ERROR <> 0 
  13838.                             GOTO UNDO
  13839.  
  13840.                         delete MSpub_identity_range where objid = @objid
  13841.                         if @@ERROR <> 0 
  13842.                             GOTO UNDO
  13843.                     end
  13844.                 end
  13845.             -- end SyncTran
  13846.             end
  13847.     end
  13848.     COMMIT TRAN
  13849.  
  13850.     IF @view_name IS NOT NULL
  13851.     BEGIN
  13852.         -- @view_name is already quoted.
  13853.         SELECT @cmd = 'drop view ' + @view_name
  13854.         exec (@cmd)
  13855.     END
  13856.  
  13857.     IF @filter_name IS NOT NULL
  13858.     BEGIN
  13859.         -- @filter_name is already quoted.
  13860.         SELECT @cmd = 'drop proc ' + @filter_name
  13861.         exec (@cmd)
  13862.     END
  13863.     /*
  13864.     ** Force the article cache to be refreshed; only if needed
  13865.     */
  13866.     if ( @ignore_distributor = 0 )
  13867.         EXECUTE dbo.sp_replflush
  13868.  
  13869.     return (0)
  13870.  
  13871. UNDO:
  13872.  
  13873.     if @@trancount > 0
  13874.     begin
  13875.         ROLLBACK TRANSACTION droparticle
  13876.         commit tran
  13877.     end
  13878.     RETURN (1)
  13879. END
  13880. go
  13881.  
  13882. EXEC dbo.sp_MS_marksystemobject sp_droparticle
  13883. GO
  13884.  
  13885. print ''
  13886. print 'Creating procedure sp_droppublication'
  13887. go
  13888.  
  13889. CREATE PROCEDURE sp_droppublication(
  13890.         @publication sysname,       /* The publication name */
  13891.         @ignore_distributor bit = 0
  13892.         ) AS
  13893.  
  13894.     /*
  13895.     ** Declarations.
  13896.     */
  13897.  
  13898.     DECLARE @article sysname
  13899.     DECLARE @cmd nvarchar(255)
  13900.     DECLARE @retcode int
  13901.     DECLARE @distributor sysname
  13902.     DECLARE @distribdb sysname
  13903.     DECLARE @distproc nvarchar (255)
  13904.     DECLARE @agentname nvarchar (40)
  13905.     DECLARE @dbname sysname
  13906.     DECLARE @virtual_id smallint
  13907.     DECLARE @ad_guidname sysname
  13908.     DECLARE @alt_snapshot_folder nvarchar(255)
  13909.     DECLARE @pub_alt_snapshot_folder nvarchar(255)
  13910.     
  13911.     SELECT @virtual_id = -1
  13912.     select @dbname = db_name()
  13913.     select @ad_guidname = NULL
  13914.     /*
  13915.     ** Security check
  13916.     */
  13917.     exec @retcode = dbo.sp_MSreplcheck_publish
  13918.     if @@ERROR <> 0 or @retcode <> 0
  13919.         return(1)
  13920.  
  13921.     /*
  13922.     ** Parameter Check:  @publication.
  13923.     ** If the @publication is 'all', drop all publications.  Otherwise,
  13924.     ** make sure the @publication is a valid non-null identifier.
  13925.     ** Delete the logreader agent after all the publications have been 
  13926.     ** removed.
  13927.     */
  13928.  
  13929.     IF LOWER(@publication) = 'all'
  13930.         BEGIN
  13931.             DECLARE hC1  CURSOR LOCAL FAST_FORWARD FOR 
  13932.                 SELECT DISTINCT name FROM syspublications 
  13933.                     WHERE pubid NOT IN 
  13934.                         (SELECT pubid FROM sysextendedarticlesview WHERE artid IN 
  13935.                             (SELECT artid FROM syssubscriptions WHERE srvid <> @virtual_id))
  13936.             OPEN hC1
  13937.             FETCH hC1 INTO @publication
  13938.             WHILE (@@fetch_status <> -1)
  13939.                 BEGIN
  13940.                     EXECUTE dbo.sp_droppublication @publication,
  13941.                         @ignore_distributor = @ignore_distributor
  13942.                     FETCH hC1 INTO @publication
  13943.                 END
  13944.             CLOSE hC1
  13945.             DEALLOCATE hC1
  13946.             RETURN (0)
  13947.         END
  13948.  
  13949.     IF @publication IS NULL
  13950.         BEGIN
  13951.             RAISERROR (14003, 16, -1)
  13952.             RETURN (1)
  13953.         END
  13954.  
  13955.     EXECUTE @retcode = dbo.sp_validname @publication
  13956.  
  13957.     IF @retcode <> 0
  13958.     RETURN (1)
  13959.  
  13960.     /*
  13961.     ** Ascertain the existence of the publication and get the taskid.
  13962.     */
  13963.     IF NOT EXISTS (SELECT *
  13964.                      FROM syspublications
  13965.                     WHERE name = @publication)
  13966.     BEGIN
  13967.         RAISERROR (20026, 11, -1, @publication)
  13968.         RETURN (1)
  13969.     END
  13970.  
  13971.     /*
  13972.     ** Check to make sure that there are no subscriptions on the publication.
  13973.     */
  13974.  
  13975.     IF EXISTS (SELECT *
  13976.                  FROM syssubscriptions a, sysextendedarticlesview b, syspublications c
  13977.                 WHERE c.name = @publication
  13978.                   AND c.pubid = b.pubid
  13979.                   AND b.artid = a.artid
  13980.                   AND a.srvid <>@virtual_id)
  13981.         BEGIN
  13982.             RAISERROR (14005, 16, -1)
  13983.             RETURN (1)
  13984.         END
  13985.  
  13986.     /*
  13987.     ** Delete all articles from the publication.
  13988.     */
  13989.  
  13990.     EXECUTE dbo.sp_droparticle @publication = @publication, 
  13991.         @article = N'all',
  13992.         @ignore_distributor = @ignore_distributor
  13993.         , @force_invalidate_snapshot = 1
  13994.     IF @@ERROR <> 0 OR  @retcode <> 0
  13995.         RETURN (1)
  13996.  
  13997.     select @ad_guidname = ad_guidname,
  13998.            @alt_snapshot_folder = alt_snapshot_folder 
  13999.       from syspublications 
  14000.      where name=@publication
  14001.  
  14002.     BEGIN TRAN
  14003.  
  14004.     /*
  14005.     ** Delete publication from syspublications.
  14006.     */
  14007.  
  14008.     DELETE FROM syspublications WHERE name = @publication
  14009.  
  14010.     IF @@ERROR <> 0
  14011.         GOTO UNDO
  14012.  
  14013.     /*
  14014.     ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
  14015.     */
  14016.     if @ignore_distributor = 0
  14017.     begin
  14018.  
  14019.         /*
  14020.         ** Get distribution server information for remote RPC call.
  14021.         */
  14022.  
  14023.         EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  14024.                                            @distribdb = @distribdb OUTPUT
  14025.  
  14026.         IF @@ERROR <> 0 OR  @retcode <> 0
  14027.             BEGIN
  14028.                 RAISERROR (14071, 16, -1)
  14029.                 RETURN (1)
  14030.             END
  14031.  
  14032.         /*
  14033.         ** Delete sync agent of Publication if it exists.
  14034.         */
  14035.         SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + '.dbo.sp_MSdrop_snapshot_agent'
  14036.         EXECUTE @retcode = @distproc 
  14037.             @publisher = @@SERVERNAME,
  14038.             @publisher_db = @dbname,
  14039.             @publication = @publication
  14040.  
  14041.         IF @@ERROR <> 0 or @retcode <> 0
  14042.             GOTO UNDO
  14043.  
  14044.         IF NOT EXISTS (SELECT * FROM syspublications  where repl_freq = 0)
  14045.             BEGIN
  14046.                 /*
  14047.                 ** Delete logreader agent, continue if drop is not successful
  14048.                 */
  14049.                 SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + '.dbo.sp_MSdrop_logreader_agent'
  14050.                 EXECUTE @retcode = @distproc @publisher = @@SERVERNAME,
  14051.                     @publisher_db = @dbname,
  14052.                     -- 'ALL' is used in sp_addpublication.
  14053.                     @publication = 'ALL'
  14054.                 IF @@ERROR <> 0 or @retcode <> 0
  14055.                     GOTO UNDO
  14056.             END
  14057.  
  14058.         /*
  14059.         ** Delete the publication at the distribution server
  14060.         */
  14061.         SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  14062.             '.dbo.sp_MSdrop_publication'
  14063.         EXECUTE @retcode = @distproc
  14064.             @publisher = @@SERVERNAME,
  14065.             @publisher_db = @dbname,
  14066.             @publication = @publication
  14067.         IF @@ERROR <> 0 or @retcode <> 0
  14068.             GOTO UNDO
  14069.         
  14070.         /*
  14071.         ** If alternate snapshot folder is specified for this publication,
  14072.         ** try to remove the publication's snapshot folder underneath the
  14073.         ** the alternate snapshot location in Distributor's context
  14074.         */
  14075.         if @alt_snapshot_folder is not null and
  14076.            @alt_snapshot_folder <> N''
  14077.         begin
  14078.  
  14079.             /* Append publication specific folder name */
  14080.             if substring(@alt_snapshot_folder,len(@alt_snapshot_folder),1)<>
  14081.                 N'\'
  14082.             begin
  14083.                 select @alt_snapshot_folder = @alt_snapshot_folder + N'\'
  14084.             end 
  14085.  
  14086.             -- UNC version
  14087.             select @pub_alt_snapshot_folder = @alt_snapshot_folder + N'unc\' + fn_replcomposepublicationsnapshotfolder(@@servername,db_name(),@publication) collate database_default
  14088.             select @distproc = fn_replquotename(RTRIM(@distributor)) collate database_default + N'.'  + fn_replquotename(@distribdb) collate database_default + 
  14089.                 N'.dbo.sp_MSreplremoveuncdir'
  14090.             -- Ignore errors as the snapshot folder may not exist at all
  14091.             EXECUTE @distproc
  14092.                 @dir = @pub_alt_snapshot_folder
  14093.  
  14094.             -- FTP-enabled version
  14095.             select @pub_alt_snapshot_folder = @alt_snapshot_folder + N'ftp\' + fn_replcomposepublicationsnapshotfolder(@@servername,db_name(),@publication) collate database_default
  14096.             select @distproc = fn_replquotename(RTRIM(@distributor)) collate database_default + N'.'  + fn_replquotename(@distribdb) collate database_default + 
  14097.                 N'.dbo.sp_MSreplremoveuncdir'
  14098.             -- Ignore errors as the snapshot folder may not exist at all
  14099.             EXECUTE @distproc
  14100.                 @dir = @pub_alt_snapshot_folder
  14101.         end
  14102.     end
  14103.  
  14104.     DECLARE @retval  INT
  14105.     EXECUTE @retval = master.dbo.xp_MSADEnabled
  14106.     if @ad_guidname is not NULL 
  14107.     begin
  14108.         if @retval = 0
  14109.         begin
  14110.             exec @retcode=master.dbo.sp_ActiveDirectory_Obj 'DELETE', 'PUBLICATION', @publication, @dbname, @ad_guidname
  14111.             if @@ERROR<>0 or @retcode<>0
  14112.             begin
  14113.                 raiserror(21369, 16, -1, @publication)
  14114.                 goto UNDO
  14115.             end
  14116.         end
  14117.         else
  14118.         begin
  14119.             RAISERROR(21254, 16, -1, @publication)
  14120.             GOTO UNDO
  14121.         end
  14122.     end
  14123.  
  14124.     COMMIT TRAN
  14125.  
  14126.     -- Since we drop publisher_database_id in sp_MSdrop_publication at the distribution db when
  14127.     -- dropping the last tran (snapshot) publication, we should call repldone here to clear
  14128.     -- repl counters and lsns. This will ensure the correctness of repl counters and avoid
  14129.     -- unnecessary log scan in the logreader if it is created again after this.
  14130.     -- Ignore all errors.
  14131.     if not exists (select * from syspublications)
  14132.     begin
  14133.         DECLARE @replicate_bit    smallint
  14134.         SELECT @replicate_bit = 2
  14135.  
  14136.         -- Used for attach and restored db.
  14137.         -- sysservers table in master db might be changed so that
  14138.         -- sp_dropsubscription won't work, which left repl bits marked in
  14139.         -- sysobjects.
  14140.         -- We have to unmark them before calling sp_repldone, otherwise
  14141.         -- A new transaction updating those objects will be considered
  14142.         -- as repl tran. It will set the truncation point to not null, which will
  14143.         -- prevent log truncation.
  14144.         UPDATE sysobjects SET replinfo =  replinfo & ~@replicate_bit
  14145.  
  14146.         /* ensure we can get in as logreader */
  14147.         exec dbo.sp_replflush
  14148.  
  14149.         /* clear repl dbtable fields unmark all xacts marked for replication */
  14150.         exec dbo.sp_repldone NULL, NULL, 0, 0, 1
  14151.     
  14152.         /* release our hold on the db as logreader */
  14153.         EXEC dbo.sp_replflush
  14154.  
  14155.         -- Run checkpoint to make sp_repldone result durable (write repl dbtable fields
  14156.         -- into the checkpoint record).
  14157.         checkpoint
  14158.     end        
  14159.  
  14160.     return (0)  
  14161.     
  14162. UNDO:
  14163.     if @@TRANCOUNT = 1
  14164.         ROLLBACK TRAN
  14165.     else
  14166.         COMMIT TRAN
  14167.     return(1)
  14168. GO
  14169.  
  14170. EXEC dbo.sp_MS_marksystemobject sp_droppublication
  14171. GO
  14172.  
  14173. print ''
  14174. print 'Creating procedure sp_dropsubscription'
  14175. go
  14176. CREATE PROCEDURE sp_dropsubscription (
  14177.     @publication sysname = NULL,   /* The publication name */
  14178.     @article sysname = NULL,       /* The article name */
  14179.     @subscriber sysname,           /* The subscriber name */
  14180.     @destination_db sysname =NULL,                /* Name of the destination database */
  14181.                                         /* If null, all the subscriptions from that
  14182.                                             subscriber will be dropped */
  14183.     @ignore_distributor bit = 0,
  14184.  
  14185.     @reserved nvarchar(10) = NULL            /* reserved, used when calling from other system */
  14186.                                             /* stored procedures, it will be set to 'internal'.*/
  14187.                                             /* It should never be used directly */
  14188.     ) AS
  14189.  
  14190.     /*
  14191.     ** Declarations.
  14192.     */
  14193.  
  14194.     DECLARE @subscriber_bit smallint
  14195.     DECLARE @cmd nvarchar(255)
  14196.     DECLARE @srvid smallint
  14197.     DECLARE @artid int
  14198.     DECLARE @retcode int
  14199.     DECLARE @active tinyint
  14200.     DECLARE @internal nvarchar(10)
  14201.     DECLARE @expand_article nvarchar(10)
  14202.     DECLARE @push tinyint
  14203.     DECLARE @virtual_id smallint
  14204.     DECLARE @login_name sysname
  14205.     DECLARE @immediate_sync bit
  14206.     DECLARE @subscription_type int
  14207.     DECLARE @qualified_subscription_name nvarchar(512)
  14208.     DECLARE @sync_method tinyint
  14209.     DECLARE @concurrent tinyint
  14210.     DECLARE @concurrent_char tinyint
  14211.  
  14212.     /*
  14213.     ** Initializations.
  14214.     */
  14215.     SET NOCOUNT ON
  14216.     SELECT @subscriber_bit = 4  /* Const: subscription server status */
  14217.     SELECT @active = 2          /* Const: subscription status 'active' */
  14218.     SELECT @push = 0        /* Const: push publication type */
  14219.     SELECT @virtual_id = -1 /* Const: virtual subscriber id */
  14220.     SELECT @internal = 'internal' /* Const: Flag of calling internally from system */
  14221.                                   /* stored procedures     */
  14222.     SELECT @expand_article = 'expand_art' 
  14223.         /* Const: Flag of calling after expand 'all' for @article  */
  14224.     SELECT @concurrent = 3
  14225.     SELECT @concurrent_char = 4
  14226.  
  14227.     /* 
  14228.     ** Security Check.
  14229.     ** We use login_name stored in syssubscriptions to manage security 
  14230.     */
  14231.  
  14232.     -- Test distributor RPC connection before open the cursor
  14233.  
  14234.     /*
  14235.     ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
  14236.     */
  14237.     if @ignore_distributor = 0
  14238.     begin
  14239.         declare @distributor sysname
  14240.         EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT
  14241.         if @@ERROR <> 0 or @retcode <> 0
  14242.             return(1)
  14243.     end
  14244.  
  14245.     /*
  14246.     ** If the @subscriber is 'all', the user wants to cancel all subscriptions
  14247.     ** to the specified article(s).
  14248.     */
  14249.  
  14250.     IF LOWER(@subscriber) = 'all'
  14251.         BEGIN
  14252.             DECLARE hCdrop_subscription1  CURSOR LOCAL FAST_FORWARD FOR 
  14253.                 SELECT DISTINCT srvname 
  14254.                     FROM master..sysservers a, syssubscriptions b 
  14255.                     WHERE srvstatus & @subscriber_bit <> 0 
  14256.                     AND a.srvid = b.srvid
  14257.  
  14258.     -- With ANSI Defaults ON, the cursor will automatically
  14259.     -- be closed on commit.   Since this proc gets called recursively, 
  14260.     -- this can happen.  So check before opening. 
  14261.     IF CURSOR_STATUS('local','hCdrop_subscription1') = -1
  14262.             OPEN hCdrop_subscription1
  14263.  
  14264.             -- must owner qual proc invoke to exec inside server on restore/attach cleanup
  14265.             FETCH hCdrop_subscription1 INTO @subscriber
  14266.             WHILE (@@fetch_status <> -1)
  14267.                 BEGIN
  14268.                     EXECUTE dbo.sp_dropsubscription 
  14269.                         @publication = @publication,
  14270.                         @article = @article,
  14271.                         @subscriber  = @subscriber,
  14272.                         @destination_db = 'all',
  14273.                         @ignore_distributor = @ignore_distributor,
  14274.                         @reserved = @reserved
  14275.  
  14276.         IF CURSOR_STATUS('local','hCdrop_subscription1') = -1
  14277.                 OPEN hCdrop_subscription1
  14278.                 FETCH hCdrop_subscription1 INTO @subscriber
  14279.                 END
  14280.             CLOSE hCdrop_subscription1
  14281.             DEALLOCATE hCdrop_subscription1
  14282.             RETURN (0)
  14283.         END
  14284.  
  14285.     
  14286.     
  14287.     /*
  14288.     ** Parameter Check: @subscriber.
  14289.     **
  14290.     ** Check if the server exists and that it is a subscription server.
  14291.     **
  14292.     */
  14293.     IF @subscriber IS NULL
  14294.         BEGIN
  14295.             SELECT @srvid = @virtual_id 
  14296.         END
  14297.     ELSE
  14298.         BEGIN
  14299.             /* validate name and get subscriber ID  and server status  */
  14300.             EXECUTE @retcode = dbo.sp_validname @subscriber
  14301.             IF @retcode <> 0
  14302.             RETURN (1)
  14303.  
  14304.             SELECT @srvid = srvid
  14305.               FROM master..sysservers
  14306.              WHERE UPPER(srvname) = UPPER(@subscriber) collate database_default
  14307.                AND (srvstatus & @subscriber_bit) <> 0
  14308.  
  14309.             IF @srvid IS NULL
  14310.                 BEGIN
  14311.                     RAISERROR (14010, 16, -1)
  14312.                     RETURN (1)
  14313.                 END
  14314.         END
  14315.  
  14316.     -- Have to check @destination_db before expanding publications and articles
  14317.     -- Otherwise, the error will not be caught because the cursor will return zero row.
  14318.     if @destination_db is not null and LOWER(@destination_db) <> 'all' 
  14319.     begin
  14320.         if not exists (select * from syssubscriptions where
  14321.             srvid = @srvid and
  14322.             dest_db = @destination_db)
  14323.         begin
  14324.             RAISERROR (14055, 11, -1)
  14325.             RETURN (1)
  14326.         end
  14327.     end
  14328.  
  14329.     /*
  14330.     ** If the @publication is 'all', the user wants to cancel all subscriptions
  14331.     ** for all publications associated with the specified @subscriber.
  14332.     */
  14333.  
  14334.     IF LOWER(@publication) = 'all'
  14335.         BEGIN
  14336.             DECLARE hCdrop_subscription2  CURSOR LOCAL FAST_FORWARD FOR 
  14337.                 SELECT DISTINCT a.name 
  14338.                     FROM syspublications a, sysextendedarticlesview b,  syssubscriptions c 
  14339.                     WHERE c.srvid = @srvid
  14340.                     -- @destination_db will not be expanded before @publication is expanded.
  14341.                     AND (c.dest_db = @destination_db 
  14342.                     or @destination_db is null
  14343.                     or LOWER(@destination_db) = 'all')
  14344.                     AND a.pubid = b.pubid 
  14345.                     AND b.artid = c.artid 
  14346.                     
  14347.             OPEN hCdrop_subscription2
  14348.             FETCH hCdrop_subscription2 INTO @publication
  14349.             WHILE (@@fetch_status <> -1)
  14350.                 BEGIN
  14351.                     EXECUTE dbo.sp_dropsubscription @publication = @publication,
  14352.                                                 @article     = 'all',
  14353.                                                 @subscriber  = @subscriber,
  14354.                                                 @destination_db = @destination_db,
  14355.                                                 @ignore_distributor = @ignore_distributor,
  14356.                                                 @reserved = @reserved
  14357.  
  14358.                     FETCH hCdrop_subscription2 INTO @publication
  14359.                 END
  14360.             CLOSE hCdrop_subscription2
  14361.             DEALLOCATE hCdrop_subscription2
  14362.             RETURN (0)
  14363.         END
  14364.  
  14365.     /*
  14366.     ** Parameter Check: @publication.
  14367.     ** Check to make sure that the publication exists and that it conforms
  14368.     ** to the rules for identifiers.
  14369.     */
  14370.  
  14371.     IF @publication IS NULL
  14372.         BEGIN
  14373.             RAISERROR (14043, 16, -1, '@publication')
  14374.             RETURN (1)
  14375.         END
  14376.  
  14377.     EXECUTE @retcode = dbo.sp_validname @publication
  14378.  
  14379.     IF @retcode <> 0
  14380.     RETURN (1)
  14381.  
  14382.     IF NOT EXISTS (SELECT * FROM syspublications WHERE name = @publication)
  14383.         BEGIN
  14384.             RAISERROR (20026, 11, -1, @publication)
  14385.             RETURN (1)
  14386.         END
  14387.  
  14388.     /* Get subscription type of the publication */
  14389.     SELECT @immediate_sync = immediate_sync, @sync_method = sync_method
  14390.         FROM syspublications WHERE name = @publication
  14391.  
  14392.     /*
  14393.     ** Parameter Check:  @article
  14394.     */
  14395.  
  14396.     /* @article can not be null     */
  14397.     IF @article IS NULL
  14398.         BEGIN
  14399.             RAISERROR (14043, 16, -1, '@article')
  14400.             RETURN (1)
  14401.         END
  14402.  
  14403.  
  14404.     /* 
  14405.     ** If publication is of concurrent sync, then all articles must
  14406.     ** be unsubscribed to
  14407.     */
  14408.     /*IF @sync_method in (@concurrent, @concurrent_char) AND
  14409.        LOWER(@article) != 'all' AND
  14410.        @reserved NOT IN( @expand_article, @internal )
  14411.     BEGIN
  14412.         RAISERROR( 14102, 16, -1 )
  14413.         RETURN (1)
  14414.     END*/
  14415.  
  14416.     /** For immediate_sync publication, @article has to be 'all'     */
  14417.     -- Relax this constraint since users will need to do this before dropping
  14418.     -- an article
  14419.     /*
  14420.     IF @reserved <> @internal AND @reserved <> @expand_article
  14421.         AND @immediate_sync = 1
  14422.         AND NOT LOWER(@article) = 'all'
  14423.         BEGIN
  14424.             RAISERROR (14122, 16, -1)
  14425.             RETURN (1)
  14426.         END
  14427.     */
  14428.  
  14429.     /*
  14430.     ** If the @article is 'all', the user wants to cancel all
  14431.     ** subscriptions on this publisher associated with the given @subscriber
  14432.     ** and @publication.
  14433.     */
  14434.  
  14435.     IF LOWER(@article) = 'all'
  14436.         BEGIN
  14437.  
  14438.             /* Make the operation automic for immediate_sync publications */
  14439.             BEGIN TRAN
  14440.  
  14441.             IF @reserved IS NULL
  14442.                 SELECT @reserved = @expand_article
  14443.  
  14444.             DECLARE hCdrop_subscription3  CURSOR LOCAL FAST_FORWARD FOR
  14445.                 SELECT DISTINCT art.name 
  14446.                     FROM sysextendedarticlesview art, syssubscriptions sub, syspublications pub 
  14447.                     WHERE sub.srvid = @srvid
  14448.                     -- @destination_db will not be expanded before @article is expanded.
  14449.                     AND (sub.dest_db = @destination_db 
  14450.                     or @destination_db is null
  14451.                     or LOWER(@destination_db) = 'all')
  14452.                     AND sub.artid = art.artid
  14453.                     AND art.pubid = pub.pubid
  14454.                     AND pub.name = @publication 
  14455.                     
  14456.             OPEN hCdrop_subscription3
  14457.             FETCH hCdrop_subscription3 INTO @article
  14458.             WHILE (@@fetch_status <> -1)
  14459.                 BEGIN
  14460.                     EXECUTE @retcode = dbo.sp_dropsubscription 
  14461.                         @publication = @publication,
  14462.                         @article = @article,
  14463.                         @subscriber = @subscriber,
  14464.                         @destination_db = @destination_db,
  14465.                         @ignore_distributor = @ignore_distributor,
  14466.                         @reserved = @reserved
  14467.                     IF @@error<>0 OR @retcode <> 0
  14468.                     BEGIN
  14469.                         CLOSE hCdrop_subscription3
  14470.                         DEALLOCATE hCdrop_subscription3
  14471.                         GOTO UNDO                        
  14472.                     END
  14473.                     FETCH hCdrop_subscription3 INTO @article
  14474.                 END
  14475.             CLOSE hCdrop_subscription3
  14476.             DEALLOCATE hCdrop_subscription3
  14477.  
  14478.             COMMIT TRAN
  14479.             RETURN (0)
  14480.         END
  14481.  
  14482.     /*
  14483.     ** Parameter Check: @article
  14484.     ** Check if the article exists.
  14485.     */
  14486.  
  14487.     /*
  14488.     EXECUTE @retcode = dbo.sp_validname @article
  14489.  
  14490.     IF @retcode <> 0
  14491.     RETURN (1)
  14492.     */
  14493.  
  14494.     SELECT @artid = artid
  14495.       FROM sysextendedarticlesview art, syspublications pub
  14496.      WHERE pub.name = @publication
  14497.        AND art.name = @article
  14498.        AND art.pubid = pub.pubid
  14499.  
  14500.     IF @artid IS NULL
  14501.         BEGIN
  14502.             RAISERROR (20027, 11, -1, @article)
  14503.         RETURN (1)
  14504.         END
  14505.  
  14506.  
  14507.     /*
  14508.     ** Parameter Check: @destination_db.
  14509.     ** Set @destination_db to current database if not specified.  Make
  14510.     ** sure that the @destination_db conforms to the rules for identifiers.
  14511.     */
  14512.  
  14513.     IF @destination_db IS NULL
  14514.     BEGIN
  14515.         /*
  14516.         ** Check if the subscription exists.
  14517.         */
  14518.  
  14519.         IF NOT EXISTS (SELECT *
  14520.                          FROM syssubscriptions
  14521.                         WHERE srvid = @srvid
  14522.                           AND artid = @artid)
  14523.         BEGIN    
  14524.                 RAISERROR (14055, 11, -1)
  14525.                 RETURN (1)
  14526.         END
  14527.         ELSE
  14528.  
  14529.         SELECT @destination_db = 'all' 
  14530.     END
  14531.     ELSE
  14532.     BEGIN
  14533.         EXECUTE @retcode = dbo.sp_validname @destination_db
  14534.         IF @retcode <> 0
  14535.         RETURN (1)
  14536.     END
  14537.  
  14538.     IF LOWER(@destination_db) = 'all' 
  14539.         BEGIN
  14540.             DECLARE hCdropsub4  CURSOR LOCAL FAST_FORWARD FOR 
  14541.                 SELECT DISTINCT dest_db
  14542.                     FROM syssubscriptions 
  14543.                     WHERE srvid = @srvid
  14544.                     AND artid = @artid
  14545.             OPEN hCdropsub4
  14546.             FETCH hCdropsub4 INTO @destination_db
  14547.             WHILE (@@fetch_status <> -1)
  14548.                 BEGIN
  14549.                     EXECUTE dbo.sp_dropsubscription 
  14550.                         @publication = @publication,
  14551.                         @article = @article,
  14552.                         @subscriber = @subscriber,
  14553.                         @destination_db = @destination_db,
  14554.                         @ignore_distributor = @ignore_distributor,
  14555.                         @reserved = @reserved
  14556.                     FETCH hCdropsub4 INTO @destination_db
  14557.                 END
  14558.             CLOSE hCdropsub4
  14559.             DEALLOCATE hCdropsub4
  14560.             RETURN (0)
  14561.         END
  14562.  
  14563.     /*
  14564.     ** Dropping virtual subscriptions is not allowed
  14565.     ** in following case:
  14566.     ** 1. non sa or dbo user
  14567.     ** 2. the stored procedure is not in internal usage mode 
  14568.     **        (called by system stored procedures)
  14569.     **
  14570.     ** Note: Only immediate_sync publications have virtual subscriptions
  14571.     ** 
  14572.     */
  14573.  
  14574.     IF  @srvid = @virtual_id  AND  (
  14575.         @reserved <> @internal)
  14576.         BEGIN
  14577.             RAISERROR (14056, 16, -1)
  14578.             RETURN (1)
  14579.         END
  14580.  
  14581.     /*
  14582.     ** Check if the subscription exists.
  14583.     */
  14584.  
  14585.     IF NOT EXISTS (SELECT *
  14586.                      FROM syssubscriptions
  14587.                     WHERE srvid = @srvid
  14588.                       AND artid = @artid
  14589.                       AND dest_db = @destination_db)
  14590.     BEGIN
  14591.             RAISERROR (14055, 11, -1)
  14592.             RETURN (1)
  14593.     END
  14594.  
  14595.  
  14596.     /* Check the current login id. It is valid only when
  14597.     ** 1. sa or dbo
  14598.     ** 2. same as the one who add the subscription.
  14599.     */
  14600.     SELECT @login_name = login_name 
  14601.          FROM syssubscriptions
  14602.         WHERE srvid = @srvid
  14603.           AND artid = @artid
  14604.           AND dest_db = @destination_db
  14605.  
  14606.     IF  suser_sname(suser_sid()) <> @login_name AND is_srvrolemember('sysadmin') <> 1  
  14607.         AND is_member ('db_owner') <> 1
  14608.     BEGIN
  14609.             SELECT @qualified_subscription_name = @subscriber + N':' + @destination_db
  14610.             RAISERROR(21120, 11, -1, @qualified_subscription_name, @publication)
  14611.             RETURN (1)
  14612.     END
  14613.  
  14614.  
  14615.     begin tran
  14616.     save TRANSACTION dropsubscription
  14617.  
  14618.         /* If dropping virtual subscriptions, reset immediate_sync_ready bit */
  14619.         IF @srvid = @virtual_id
  14620.         BEGIN
  14621.             UPDATE syspublications SET immediate_sync_ready = 0
  14622.                 WHERE
  14623.                     name = @publication and
  14624.                     immediate_sync = 1 and
  14625.                     immediate_sync_ready = 1
  14626.             IF @@ERROR <> 0
  14627.                 goto UNDO
  14628.         END
  14629.  
  14630.         /*
  14631.         ** Change the status of the subscription to 'inactive'.
  14632.         */
  14633.  
  14634.         EXECUTE @retcode = dbo.sp_changesubstatus @publication = @publication,
  14635.                                               @article = @article,
  14636.                                               @subscriber = @subscriber,
  14637.                                               @status = 'inactive',
  14638.                                               @destination_db = @destination_db,
  14639.                                               @ignore_distributor = @ignore_distributor
  14640.         IF @@ERROR <> 0 OR @retcode <> 0
  14641.         BEGIN
  14642.             if @@trancount > 0
  14643.             begin
  14644.                 ROLLBACK TRANSACTION dropsubscription
  14645.                 commit tran
  14646.             end
  14647.             RETURN (1)
  14648.         END
  14649.  
  14650.     /* Read the subscription_type befor removing the syssubscriptions row */
  14651.     select @subscription_type = subscription_type from syssubscriptions
  14652.         WHERE artid = @artid
  14653.         AND srvid = @srvid
  14654.         AND dest_db = @destination_db
  14655.     /*
  14656.     ** Remove subscription from syssubscriptions.
  14657.     */
  14658.     DELETE syssubscriptions
  14659.      WHERE artid = @artid
  14660.        AND srvid = @srvid
  14661.        AND dest_db = @destination_db
  14662.  
  14663.     IF @@ERROR <> 0
  14664.     BEGIN
  14665.         if @@trancount > 0
  14666.         begin
  14667.             ROLLBACK TRANSACTION dropsubscription
  14668.             commit tran
  14669.         end
  14670.         RETURN (1)
  14671.     END
  14672.  
  14673.     /* Call sp_MSunregistersubscription so that the reg entries get deleted (for push subscriptions) */
  14674.     if @subscription_type = @push
  14675.         begin
  14676.             declare @publisher_db sysname
  14677.             set @publisher_db = DB_NAME()
  14678.             exec @retcode = dbo.sp_MSunregistersubscription @publisher = @@SERVERNAME,
  14679.                                 @publisher_db = @publisher_db,
  14680.                                 @publication = @publication,
  14681.                                 @subscriber = @subscriber,
  14682.                                 @subscriber_db = @destination_db
  14683.  
  14684.             IF @retcode<>0 or @@ERROR<>0
  14685.                 GOTO UNDO
  14686.         end             
  14687.   
  14688.     COMMIT TRANSACTION
  14689.     RETURN (0)
  14690.  
  14691. UNDO:
  14692.     IF @@TRANCOUNT = 1
  14693.         ROLLBACK TRAN
  14694.     ELSE
  14695.         COMMIT TRAN
  14696.     RETURN(1)
  14697. go
  14698.  
  14699. EXEC dbo.sp_MS_marksystemobject sp_dropsubscription
  14700. GO
  14701.  
  14702. print ''
  14703. print 'Creating procedure sp_subscribe'
  14704. go
  14705. CREATE PROCEDURE sp_subscribe (
  14706.     @publication sysname,          /* publication name */
  14707.     @article sysname = 'all',          /* article name */
  14708.     @destination_db sysname = NULL,  /* subscriber database */
  14709.     @sync_type nvarchar (15) = 'automatic' /* subscription sync type */
  14710.     ) AS
  14711.  
  14712.     -- New 7.0 sp_addsubscription parameters
  14713.     DECLARE @subscriber                  sysname
  14714.     DECLARE @status                      sysname
  14715.     DECLARE @subscription_type           nvarchar(4)
  14716.     DECLARE @update_mode                 nvarchar(15)
  14717.     DECLARE @loopback_detection          nvarchar(5)
  14718.     DECLARE @enabled_for_syncmgr         nvarchar(5)
  14719.     DECLARE @retcode                     int
  14720.  
  14721.     SET NOCOUNT ON
  14722.  
  14723.     -- sp_subscribe has to be called from a remote subscriber 
  14724.     -- If not, we state that it is unsupported
  14725.     SELECT @subscriber = @@REMSERVER
  14726.     IF @subscriber IS NULL
  14727.     BEGIN
  14728.       RAISERROR (21023, 16, -1,'sp_subscribe')
  14729.       RETURN(1)
  14730.     END
  14731.     
  14732.     SELECT @status = NULL
  14733.     SELECT @subscription_type = 'push'
  14734.     SELECT @update_mode = 'read only'
  14735.     SELECT @loopback_detection = 'false'
  14736.     SELECT @enabled_for_syncmgr = 'false'
  14737.  
  14738.     -- Call sp_addsubscription to do the actual work
  14739.     EXEC @retcode = dbo.sp_addsubscription @publication = @publication,
  14740.                                            @article = @article,
  14741.                                            @destination_db = @destination_db,
  14742.                                            @sync_type = @sync_type,
  14743.                                            @subscriber = @subscriber,
  14744.                                            @status = @status,
  14745.                                            @subscription_type = @subscription_type,
  14746.                                            @update_mode = @update_mode,
  14747.                                            @loopback_detection = @loopback_detection,
  14748.                                            @enabled_for_syncmgr = @enabled_for_syncmgr
  14749.                                         
  14750.     RETURN @retcode   
  14751. go
  14752.  
  14753. EXEC dbo.sp_MS_marksystemobject sp_subscribe
  14754. GO
  14755.  
  14756. print ''
  14757. print 'Creating procedure sp_unsubscribe'
  14758. go
  14759. CREATE PROCEDURE sp_unsubscribe (
  14760.     @publication sysname = NULL,       /* publication name */
  14761.     @article sysname = NULL            /* article name */
  14762.     ) AS
  14763.  
  14764.     -- New 7.0 sp_dropsubscription parameters
  14765.     DECLARE @subscriber     sysname
  14766.     DECLARE @destination_db sysname    
  14767.     DECLARE @retcode        int 
  14768.  
  14769.     SET NOCOUNT ON
  14770.     
  14771.     -- sp_unsubscribe has to be callled from a remote subscriber
  14772.     -- If not, we state that it is unsupported
  14773.     SELECT @subscriber = @@REMSERVER
  14774.     IF @subscriber IS NULL
  14775.     BEGIN
  14776.         RAISERROR (21023, 16, -1,'sp_unsubscribe')
  14777.         RETURN(1)
  14778.     END
  14779.  
  14780.     -- 6.5 didn't support having multiple databases on the same subscriber
  14781.     -- subscribing to the same publication so here, all subscriptions to the
  14782.     -- same publication will be dropped 
  14783.     SELECT @destination_db = NULL
  14784.     
  14785.     -- Call sp_dropsubscription to do the real work
  14786.     EXEC @retcode = sp_dropsubscription @publication = @publication,
  14787.                                         @article = @article,
  14788.                                         @subscriber = @subscriber,
  14789.                                         @destination_db = @destination_db
  14790.     RETURN @retcode
  14791.     
  14792. go
  14793.  
  14794. EXEC dbo.sp_MS_marksystemobject sp_unsubscribe
  14795. GO
  14796.  
  14797. print ''
  14798. print 'Creating procedure sp_refreshsubscriptions'
  14799. go
  14800.  
  14801. CREATE PROCEDURE sp_refreshsubscriptions (
  14802.     @publication sysname       /* Publication name */
  14803.     ) AS
  14804.  
  14805.     SET NOCOUNT ON
  14806.  
  14807.     /*
  14808.     ** Declarations.
  14809.     */
  14810.  
  14811.     DECLARE @article  sysname 
  14812.     DECLARE @subscriber sysname
  14813.     DECLARE @dest_db sysname
  14814.     DECLARE @retcode int
  14815.     DECLARE @pubid int
  14816.     DECLARE @immediate_sync bit 
  14817.     DECLARE @no_sync tinyint
  14818.     DECLARE @subscription_type_id int
  14819.     DECLARE @subscription_type nvarchar(4)
  14820.     DECLARE @virtual smallint
  14821.     DECLARE @srvid smallint
  14822.     DECLARE @sync_typeid int
  14823.     DECLARE @automatic tinyint
  14824.     DECLARE @sync_type nvarchar(9)
  14825.  
  14826.     SELECT @no_sync = 2
  14827.     SELECT @virtual = -1
  14828.     SELECT @automatic = 1
  14829.     /*
  14830.     ** Security Check
  14831.     */
  14832.     exec @retcode = dbo.sp_MSreplcheck_publish
  14833.     if @@ERROR <> 0 or @retcode <> 0
  14834.         return(1)
  14835.  
  14836.     /*
  14837.     ** Check to see if the database has been activated for publication.
  14838.     */
  14839.  
  14840.     IF (SELECT category & 1
  14841.           FROM master..sysdatabases
  14842.          WHERE name = DB_NAME() collate database_default) = 0
  14843.  
  14844.     BEGIN
  14845.             RAISERROR (14013, 16, -1)
  14846.         RETURN (1)
  14847.     END
  14848.  
  14849.  
  14850.     /*
  14851.     ** Parameter Check:  @publication.
  14852.     ** Make sure that the publication exists
  14853.     */
  14854.  
  14855.     IF @publication IS NULL
  14856.         BEGIN
  14857.             RAISERROR (14043, 16, -1, '@publication')
  14858.             RETURN (1)
  14859.         END
  14860.  
  14861.     EXECUTE @retcode = dbo.sp_validname @publication
  14862.  
  14863.     IF @@ERROR <> 0 OR @retcode <> 0
  14864.     RETURN (1)
  14865.  
  14866.     SELECT @pubid = pubid
  14867.         FROM syspublications WHERE name = @publication
  14868.  
  14869.     IF @pubid IS NULL
  14870.         BEGIN
  14871.             RAISERROR (20026, 11, -1, @publication)
  14872.             RETURN (1)
  14873.         END
  14874.     
  14875.     
  14876.     /* Add real subscription to the new articles  */
  14877.     /* Open a cursor on all the pending subscriptions, that is */
  14878.     /* All the subscriptions on the publication that */
  14879.     /* are not on an article in the publication. */
  14880.     /* not including virtual subscriptions */
  14881.  
  14882.     DECLARE hCrefreshsubscriptions CURSOR LOCAL FAST_FORWARD FOR
  14883.         SELECT DISTINCT art1.name, subs1.dest_db, subs1.srvid
  14884.             FROM syssubscriptions subs1, sysextendedarticlesview art1
  14885.             WHERE art1.pubid = @pubid AND
  14886.                   subs1.srvid <> @virtual AND
  14887.                   EXISTS (SELECT * FROM syssubscriptions subs2, sysextendedarticlesview art2
  14888.                     WHERE subs2.srvid = subs1.srvid AND
  14889.                           subs2.dest_db = subs1.dest_db AND
  14890.                           subs2.artid = art2.artid AND
  14891.                           art2.pubid = @pubid) AND
  14892.                   NOT EXISTS ( SELECT * FROM syssubscriptions subs3 
  14893.                     WHERE  subs3.artid = art1.artid AND
  14894.                            subs3.srvid = subs1.srvid AND
  14895.                            subs3.dest_db = subs1.dest_db)
  14896.     FOR READ ONLY
  14897.     OPEN hCrefreshsubscriptions
  14898.     FETCH hCrefreshsubscriptions INTO @article,  @dest_db, @srvid
  14899.             
  14900.     
  14901.     WHILE (@@fetch_status <> -1)
  14902.     BEGIN
  14903.  
  14904.         /* 
  14905.         ** Get subscription type on the publication
  14906.         */ 
  14907.         SELECT @subscription_type_id = subs.subscription_type,
  14908.             @sync_typeid = subs.sync_type
  14909.          from 
  14910.             sysextendedarticlesview art, syssubscriptions subs where 
  14911.             art.pubid = @pubid AND
  14912.             subs.srvid = @srvid AND
  14913.             subs.dest_db = @dest_db AND
  14914.             subs.artid = art.artid
  14915.  
  14916.         /* 
  14917.         ** only do it if the subscription all have the same subscription type
  14918.         ** and sync_type
  14919.         */
  14920.         IF NOT EXISTS (SELECT * from 
  14921.             sysextendedarticlesview art, syssubscriptions subs where 
  14922.             art.pubid = @pubid AND
  14923.             subs.srvid = @srvid AND
  14924.             subs.dest_db = @dest_db AND
  14925.             subs.artid = art.artid AND
  14926.             (subscription_type <> @subscription_type_id OR
  14927.             sync_type <> @sync_typeid))
  14928.         BEGIN
  14929.             IF @subscription_type_id = 0
  14930.                 SELECT @subscription_type = 'push'
  14931.             ELSE
  14932.                 SELECT @subscription_type = 'pull'
  14933.  
  14934.             if @sync_typeid = @automatic
  14935.                 SELECT @sync_type = 'automatic'
  14936.             else
  14937.                 SELECT @sync_type = 'none'
  14938.  
  14939.             /* 
  14940.             ** Get the server name
  14941.             */
  14942.             SELECT @subscriber = srvname FROM master.dbo.sysservers 
  14943.                 WHERE srvid = @srvid
  14944.  
  14945.             EXECUTE @retcode  = dbo.sp_addsubscription 
  14946.                         @publication = @publication, 
  14947.                         @article = @article, 
  14948.                         @subscriber = @subscriber, 
  14949.                         @destination_db = @dest_db, 
  14950.                         @sync_type = @sync_type, 
  14951.                         @status = NULL, 
  14952.                         @subscription_type = @subscription_type,
  14953.                         @reserved = 'internal'
  14954.             IF @@ERROR <> 0 OR @retcode <> 0
  14955.             BEGIN
  14956.                 CLOSE hCrefreshsubscriptions
  14957.                 DEALLOCATE hCrefreshsubscriptions
  14958.                 RETURN (1)
  14959.             END
  14960.         END
  14961.         FETCH hCrefreshsubscriptions INTO @article, @dest_db, @srvid
  14962.     END
  14963.     
  14964.     CLOSE hCrefreshsubscriptions
  14965.     DEALLOCATE hCrefreshsubscriptions
  14966.  
  14967. GO
  14968.  
  14969. EXEC dbo.sp_MS_marksystemobject sp_refreshsubscriptions
  14970. GO
  14971.  
  14972. print ''
  14973. print 'Creating procedure sp_MSpublishdb'
  14974. go
  14975.  
  14976. CREATE PROCEDURE sp_MSpublishdb(
  14977.       @value     sysname,
  14978.       @ignore_distributor bit = 0
  14979.     ) AS
  14980.  
  14981.     SET NOCOUNT ON
  14982.  
  14983.     /*
  14984.     ** Declarations.
  14985.     */
  14986.     declare @quoted_db      sysname
  14987.     declare @db_name        sysname
  14988.     declare @command        nvarchar(255)
  14989.     declare @description    nvarchar(500)
  14990.     declare @category_name  nvarchar(100)
  14991.     DECLARE @agentname      nvarchar(300)
  14992.     DECLARE @dbname         sysname 
  14993.     DECLARE @retcode        int
  14994.     DECLARE @distributor    sysname
  14995.     DECLARE @distribdb      sysname
  14996.     DECLARE @distproc       nvarchar (255)
  14997.     /*
  14998.     ** Initialization
  14999.     */
  15000.  
  15001.     SELECT @dbname = DB_NAME()
  15002.  
  15003.     /*
  15004.     ** Parameter check
  15005.     ** @value
  15006.     */
  15007.     IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true','false')
  15008.     BEGIN
  15009.       RAISERROR(14137,16,-1)
  15010.       RETURN(1)
  15011.     END
  15012.  
  15013.     /*
  15014.     ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
  15015.     */
  15016.     if @ignore_distributor = 0
  15017.     begin
  15018.         /*
  15019.         ** Test to see if the distributor is installed and online.
  15020.         */
  15021.         EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  15022.            @distribdb   = @distribdb OUTPUT
  15023.  
  15024.         IF @@ERROR <> 0 or @retcode <> 0 or @distributor IS NULL or @distribdb IS NULL
  15025.         BEGIN
  15026.             IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  15027.                 RAISERROR (20028, 16, -1)
  15028.             ELSE
  15029.                 RAISERROR (20029, 16, -1)
  15030.             RETURN (1)
  15031.         END
  15032.     end
  15033.  
  15034.     /*
  15035.     ** Enable the database for publishing.
  15036.     */
  15037.     IF LOWER(@value collate SQL_Latin1_General_CP1_CS_AS) = 'true'
  15038.     BEGIN
  15039.  
  15040.         /*
  15041.         ** Drop and then create central publish tables
  15042.         */
  15043.  
  15044.         /* 
  15045.         ** Drop first if exists
  15046.         */
  15047.  
  15048.         EXEC @retcode = dbo.sp_MSdrop_pub_tables
  15049.         IF @@ERROR <> 0 or @retcode <> 0
  15050.         BEGIN
  15051.             return (1)
  15052.         END
  15053.  
  15054.         /*
  15055.         ** Create central publish tables
  15056.         */
  15057.  
  15058.         EXEC @retcode = dbo.sp_MScreate_pub_tables
  15059.         IF @@ERROR <> 0 or @retcode <> 0
  15060.         BEGIN
  15061.             return (1)
  15062.         END
  15063.     END
  15064.  
  15065.     ELSE    /* Disable the database for publishing. */
  15066.     BEGIN
  15067.         /*
  15068.         ** Remove all subscriptions in the database.
  15069.         ** WARNING : must owner qualify proc calls for these to run inside server on restore/attach
  15070.         */
  15071.         EXEC @retcode = dbo.sp_dropsubscription @publication = 'all',
  15072.             @article = 'all', @subscriber = 'all', 
  15073.             @ignore_distributor = @ignore_distributor
  15074.         IF @@ERROR <> 0 or @retcode <> 0
  15075.         BEGIN
  15076.             return (1)
  15077.         END
  15078.  
  15079.         -- Used for attach and restored db.
  15080.         -- sysservers table in master db might be changed so that
  15081.         -- sp_dropsubscription won't work. Delete the table directly.
  15082.  
  15083.         delete syssubscriptions where srvid >= 0
  15084.         IF @@ERROR <> 0 
  15085.         BEGIN
  15086.             return (1)
  15087.         END
  15088.  
  15089.         /*
  15090.         ** Remove all publications and articles in the database.
  15091.         ** sp_droppublication will also forcefully unmark repl bits in sysobjects
  15092.         ** and call sp_repldone when dropping the last
  15093.         ** publication.
  15094.         */
  15095.         EXEC @retcode = dbo.sp_droppublication @publication = 'all', 
  15096.             @ignore_distributor = @ignore_distributor
  15097.         IF @@ERROR <> 0 or @retcode <> 0
  15098.         BEGIN
  15099.             return (1)
  15100.         END
  15101.  
  15102.         /* 
  15103.         ** Drop central publish tables
  15104.         */ 
  15105.         EXEC @retcode = dbo.sp_MSdrop_pub_tables
  15106.         IF @@ERROR <> 0 or @retcode <> 0
  15107.         BEGIN
  15108.             return (1)
  15109.         END
  15110.  
  15111.       END
  15112.     return (0)
  15113. GO
  15114.  
  15115. EXEC dbo.sp_MS_marksystemobject sp_MSpublishdb
  15116. GO
  15117.  
  15118. print ''
  15119. print 'Creating procedure sp_MSactivate_auto_sub'
  15120. go
  15121.  
  15122. CREATE PROCEDURE sp_MSactivate_auto_sub (
  15123.     @publication sysname,        /* Publication name */
  15124.     @article sysname,
  15125.     @status sysname = 'active',
  15126.     @schemastabilityonly int = 0
  15127.     ) AS
  15128.  
  15129.     SET NOCOUNT ON
  15130.  
  15131.     DECLARE @retcode int
  15132.  
  15133.     /*
  15134.     ** Security Check.
  15135.     */
  15136.     exec @retcode = dbo.sp_MSreplcheck_publish
  15137.     if @@ERROR <> 0 or @retcode <> 0
  15138.         return(1)
  15139.  
  15140.     /*
  15141.     ** Check to see if the database has been activated for publication.
  15142.     */
  15143.  
  15144.     IF (SELECT category & 1
  15145.           FROM master..sysdatabases
  15146.          WHERE name = DB_NAME() collate database_default) = 0
  15147.  
  15148.     BEGIN
  15149.         RAISERROR (14013, 16, -1)
  15150.         RETURN (1)
  15151.     END
  15152.  
  15153.     -- parameter check: @status:  
  15154.  
  15155.     IF LOWER(@status collate SQL_Latin1_General_CP1_CS_AS) not in (N'active', N'initiated')
  15156.     BEGIN
  15157.         RAISERROR(21156, 16, -1)
  15158.         RETURN 1
  15159.     END
  15160.  
  15161.     /*
  15162.     ** Parameter Check:  @publication.
  15163.     ** Make sure that the publication exists and the publication is not push type
  15164.     */
  15165.  
  15166.     IF @publication IS NULL
  15167.         BEGIN
  15168.             RAISERROR (14043, 16, -1, '@publication')
  15169.             RETURN (1)
  15170.         END
  15171.  
  15172.     EXECUTE @retcode = dbo.sp_validname @publication
  15173.     IF @@ERROR <> 0 OR @retcode <> 0
  15174.         RETURN (1)
  15175.     
  15176.     BEGIN TRAN
  15177.  
  15178.     IF @status = N'active'
  15179.     BEGIN
  15180.         UPDATE syspublications SET immediate_sync_ready = 1 
  15181.             WHERE
  15182.                 name = @publication AND
  15183.                 immediate_sync = 1 AND
  15184.                 immediate_sync_ready <> 1
  15185.         IF @@ERROR <> 0
  15186.         BEGIN
  15187.             GOTO UNDO
  15188.             RETURN (1)
  15189.         END
  15190.     END
  15191.  
  15192.     EXECUTE @retcode = dbo.sp_changesubstatus 
  15193.         @publication = @publication,
  15194.         @article = @article,
  15195.         @status = @status,
  15196.         @from_auto_sync = 1,
  15197.         @schemastabilityonly = @schemastabilityonly
  15198.  
  15199.     IF @@ERROR <> 0 OR @retcode <> 0
  15200.     BEGIN
  15201.         GOTO UNDO
  15202.         RETURN (1)
  15203.     END
  15204.     
  15205.     COMMIT TRAN
  15206.     RETURN(0)
  15207.  
  15208. UNDO:
  15209.     IF @@TRANCOUNT = 1
  15210.         ROLLBACK TRAN
  15211.     ELSE
  15212.         COMMIT TRAN
  15213.  
  15214. GO
  15215.  
  15216. EXEC dbo.sp_MS_marksystemobject sp_MSactivate_auto_sub
  15217. GO
  15218.  
  15219. raiserror('Creating procedure sp_MSget_synctran_commands', 0,1)
  15220. GO
  15221. CREATE PROCEDURE sp_MSget_synctran_commands(
  15222.     @publication sysname    /* publication name */,
  15223.     @article sysname = 'all',
  15224.     @command_only bit = 0   /* 0 if called by snapshot agent, 1 if called by sp_script_..., */
  15225. ) AS
  15226. BEGIN
  15227.     SET NOCOUNT ON
  15228.     DECLARE @artid int
  15229.             ,@tabid int
  15230.             ,@retcode int
  15231.             ,@art_type tinyint        
  15232.             ,@filter_id int
  15233.             ,@filter_clause nvarchar(4000)
  15234.             ,@columns binary(32)
  15235.             ,@distributor sysname
  15236.             ,@pubid int
  15237.             ,@art_name sysname 
  15238.             ,@posted_synctran_artid int
  15239.             ,@dest_table sysname 
  15240.             ,@dest_owner sysname
  15241.             ,@proc_owner sysname
  15242.  
  15243.             ,@ts_col sysname
  15244.             ,@replcmd nvarchar(4000)
  15245.             ,@insproc sysname
  15246.             ,@updproc sysname
  15247.             ,@delproc sysname
  15248.             ,@cftproc sysname
  15249.             ,@cft_table sysname
  15250.             ,@is_synctran bit
  15251.             ,@is_queued bit
  15252.             ,@identity_col sysname
  15253.             ,@identity_prop tinyint
  15254.             ,@identity_support bit
  15255.  
  15256.  
  15257.     /*
  15258.     ** Initializations.
  15259.     */
  15260.     select @posted_synctran_artid = 0 
  15261.     select @identity_support = 0
  15262.  
  15263.     /* 
  15264.     ** Security Check.
  15265.     ** We use login_name stored in syssubscriptions to manage security 
  15266.     ** Do a relaxed security check here.
  15267.     */
  15268.     exec @retcode = dbo.sp_MSreplcheck_publish
  15269.     if @@ERROR <> 0 or @retcode <> 0
  15270.         return(1)
  15271.  
  15272.     /*
  15273.     ** Parameter Check:  @publication
  15274.     ** Check to make sure that the publication exists, that it's not NULL,
  15275.     ** and that it conforms to the rules for identifiers.
  15276.     */
  15277.  
  15278.     IF @publication IS NULL
  15279.         BEGIN
  15280.             RAISERROR (14043, 16, -1, '@publication')
  15281.             RETURN (1)
  15282.         END
  15283.  
  15284.     EXECUTE @retcode = dbo.sp_validname @publication
  15285.     IF @@ERROR <> 0 OR @retcode <> 0
  15286.     RETURN (1)
  15287.  
  15288.     declare @independent_agent bit
  15289.     SELECT @pubid = pubid,
  15290.             @independent_agent = independent_agent,
  15291.             @is_synctran = allow_sync_tran,
  15292.             @is_queued = allow_queued_tran
  15293.     FROM syspublications 
  15294.     WHERE name = @publication
  15295.  
  15296.     IF @pubid IS NULL
  15297.     BEGIN
  15298.         RAISERROR (20026, 11, -1, @publication)
  15299.         RETURN (1)
  15300.     END
  15301.  
  15302.     -- If the publication does not allow sync tran or queued tran return nothing
  15303.     IF (@is_synctran = 0 AND @is_queued = 0)
  15304.         RETURN(0)
  15305.  
  15306.     --
  15307.     -- get the distributor details for this publisher
  15308.     --
  15309.     exec @retcode = dbo.sp_helpdistributor @distributor = @distributor OUTPUT
  15310.     if (@@ERROR != 0 OR @retcode != 0 or @distributor IS NULL)
  15311.     begin
  15312.         raiserror('sp_MSget_synctran_commands(debug): could not get distributor info', 16, 1)
  15313.         RETURN (1)
  15314.     end
  15315.  
  15316.     CREATE TABLE #art_commands (artid int NOT NULL, commands nvarchar(4000) collate database_default null, id int identity NOT NULL)
  15317.     
  15318.     declare @all_article bit 
  15319.  
  15320.     if lower(@article) = 'all'
  15321.         select @all_article = 1
  15322.     else
  15323.         select @all_article = 0
  15324.  
  15325.     -- Construct ver check cmd
  15326.     declare @ver_check_cmd nvarchar(4000)
  15327.     -- Construct message.
  15328.     select @ver_check_cmd = formatmessage(21273)
  15329.     select @ver_check_cmd = '''' + replace(@ver_check_cmd, '''', '''''') + ''''
  15330.     select @ver_check_cmd = 'if @@microsoftversion<0x07320000 raiserror(' + 
  15331.         @ver_check_cmd + ',16, -1)'
  15332.  
  15333.     DECLARE hCsynctran_arts CURSOR LOCAL FAST_FORWARD FOR
  15334.         SELECT art.artid,
  15335.                art.objid,
  15336.                
  15337.                art.dest_table,
  15338.                art.dest_owner,
  15339.                art.name,
  15340.                art.type,
  15341.                art.filter,
  15342.                art.columns
  15343.           FROM sysarticles art,
  15344.                syspublications pub
  15345.          WHERE pub.pubid = @pubid and
  15346.                pub.pubid = art.pubid and
  15347.                (art.type & 0x1) = 1 and
  15348.                (art.name = @article or
  15349.                @all_article = 1)
  15350.     FOR READ ONLY
  15351.  
  15352.     OPEN hCsynctran_arts
  15353.  
  15354.     FETCH hCsynctran_arts INTO @artid, @tabid, @dest_table, @dest_owner, @art_name, 
  15355.         @art_type, @filter_id, @columns
  15356.     
  15357.     WHILE (@@fetch_status <> -1)
  15358.     BEGIN
  15359.  
  15360.     /*
  15361.     ** Determine conflict detection method 
  15362.     */
  15363.         -- Determine if table has timestamp property
  15364.         select @ts_col = NULL
  15365.         if ObjectProperty(@tabid, 'TableHasTimestamp') = 1 
  15366.         begin
  15367.             exec dbo.sp_MSis_col_replicated @publication, @art_name, 
  15368.                 'timestamp', @ts_col OUTPUT
  15369.         end
  15370.  
  15371.         select @posted_synctran_artid = @artid
  15372.  
  15373.         select @insproc = null, @updproc = null, @delproc = null
  15374.  
  15375.         -- Get sproc names and owner name of the sprocs
  15376.         -- Note artid is unique
  15377.         select @insproc = o.name, @proc_owner = u.name from sysobjects o, sysarticleupdates a, sysusers u
  15378.         where a.artid = @artid and a.sync_ins_proc = o.id and
  15379.             u.uid = o.uid
  15380.  
  15381.         select @updproc = o.name from sysobjects o, sysarticleupdates a
  15382.         where a.artid = @artid and a.sync_upd_proc = o.id
  15383.     
  15384.         select @delproc = o.name from sysobjects o, sysarticleupdates a
  15385.         where a.artid = @artid and a.sync_del_proc = o.id 
  15386.  
  15387.         select @cftproc = o.name from sysobjects o, sysarticleupdates a
  15388.         where a.artid = @artid and a.ins_conflict_proc = o.id 
  15389.         
  15390.         if @insproc IS NULL
  15391.         begin
  15392.             CLOSE hCsynctran_arts
  15393.             DEALLOCATE hCsynctran_arts
  15394.             RAISERROR (14043, 11, -1, '@insproc')
  15395.             RETURN (1)
  15396.         end
  15397.  
  15398.         if @updproc IS NULL 
  15399.         begin
  15400.             CLOSE hCsynctran_arts
  15401.             DEALLOCATE hCsynctran_arts
  15402.             RAISERROR (14043, 11, -1, '@updproc')
  15403.             RETURN (1)
  15404.         end
  15405.  
  15406.         if @delproc IS NULL
  15407.         begin
  15408.             CLOSE hCsynctran_arts
  15409.             DEALLOCATE hCsynctran_arts
  15410.             RAISERROR (14043, 11, -1, '@delproc')
  15411.             RETURN (1)
  15412.         end
  15413.  
  15414.         if (@cftproc IS NULL)
  15415.         begin
  15416.             if (@is_queued = 1)
  15417.             begin
  15418.                 CLOSE hCsynctran_arts
  15419.                 DEALLOCATE hCsynctran_arts
  15420.                 RAISERROR (14043, 11, -1, '@cftproc')
  15421.                 RETURN (1)
  15422.             end            
  15423.         end
  15424.  
  15425.         -- Determine if published table has identity  col
  15426.         select @identity_col = NULL
  15427.         select @identity_support = 0
  15428.         if ObjectProperty(@tabid, 'TableHasIdentity') = 1 
  15429.             exec @retcode = dbo.sp_MSis_col_replicated @publication, @art_name, 'identity', @identity_col OUTPUT
  15430.         if @identity_col is not null
  15431.             select @identity_support = identity_support from sysarticleupdates where artid = @artid
  15432.                 
  15433.         -- Horizontal partition
  15434.         select @filter_clause = 'null'
  15435.         if @filter_id <> 0
  15436.         begin
  15437.             -- We don't handle manual filters;  allow all updates
  15438.             if ((@art_type & 0x3) <> 0x3) 
  15439.                 select @filter_clause = RTRIM(LTRIM(CONVERT(nvarchar(4000), filter_clause)))
  15440.                      from sysarticles where artid = @artid
  15441.         end
  15442.     
  15443.         declare @fullname nvarchar(512)
  15444.         declare @indkey       int
  15445.         declare @indid        int
  15446.         declare @key          sysname
  15447.         declare @col          sysname
  15448.         declare @this_col      int
  15449.         declare @src_cols      int
  15450.         declare @primary_key_bitmap varbinary(4000)
  15451.         declare @byte varbinary(1)
  15452.         declare @i_byte            int
  15453.         declare @num_bytes        int
  15454.         declare @i_bit            tinyint    
  15455.         declare @bitmap_str    varchar(8000)
  15456.         declare @bitmap            varbinary(4000)
  15457.  
  15458.  
  15459.         -- Get qualified name
  15460.         exec dbo.sp_MSget_qualified_name @tabid, @fullname output
  15461.         
  15462.         -- Get number of columns in the partition.
  15463.         exec dbo.sp_MSget_col_position @tabid, @columns, @key, @col output, 
  15464.             @this_col output, 
  15465.             1, -- Get num of columns in the partition.
  15466.             @src_cols output
  15467.         select @num_bytes = @src_cols / 8 + 1
  15468.     
  15469.         -- Set varbinary length
  15470.         set @byte = 0
  15471.         set @primary_key_bitmap = @byte
  15472.         set @i_byte = 1
  15473.         while @i_byte < @num_bytes
  15474.         begin
  15475.             set @primary_key_bitmap = @primary_key_bitmap + @byte
  15476.             set @i_byte = @i_byte + 1
  15477.         end
  15478.     
  15479.         -- get index id
  15480.         exec @indid = dbo.sp_MStable_has_unique_index @tabid
  15481.         set @indkey = 1
  15482.         while @indkey < 16 and index_col(@fullname, @indid, @indkey) is not null
  15483.         begin
  15484.             set @key = index_col(@fullname, @indid, @indkey)
  15485.             exec dbo.sp_MSget_col_position @tabid, @columns, @key, @col output, @this_col output
  15486.             set @i_byte = 1 + (@this_col-1) / 8
  15487.             set @i_bit  = power(2, (@this_col-1) % 8 )
  15488.             set @primary_key_bitmap 
  15489.                 = substring(@primary_key_bitmap, 1, @i_byte - 1)
  15490.                 + convert(binary(1), substring(@primary_key_bitmap, @i_byte, 1) | @i_bit)
  15491.                 + substring(@primary_key_bitmap, @i_byte + 1, @num_bytes - @i_byte)
  15492.             select @indkey = @indkey + 1
  15493.         end
  15494.         exec @retcode = master..xp_varbintohexstr @primary_key_bitmap, @bitmap_str output
  15495.         if @retcode <> 0 or @@error <> 0
  15496.             return 1
  15497.  
  15498.         if @dest_owner is null 
  15499.         begin
  15500.             select @dest_owner = N'null'
  15501.         end
  15502.         select @replcmd = '{call sp_addsynctriggers (N' + 
  15503.             quotename(@dest_table,'''') + ', N' + 
  15504.             quotename(@dest_owner,'''') + ', N' +  
  15505.             quotename(@@SERVERNAME,'''') + ', N' +   
  15506.             quotename(db_name(),'''') + ', N' + 
  15507.             quotename(@publication,'''') + ', N' +  
  15508.             quotename(@insproc,'''') + ', N' +   
  15509.             quotename(@updproc,'''') + ', N' +   
  15510.             quotename(@delproc,'''') + ', N' + 
  15511.             ISNULL(quotename(@cftproc,''''), '''null''')  + ', N' + 
  15512.             quotename(@proc_owner,'''') + ', N' + 
  15513.             ISNULL(quotename(@identity_col,''''),'''null''') + ', N' + 
  15514.             ISNULL(quotename(@ts_col,''''), '''null''') + ', N''' + 
  15515.             replace(@filter_clause,'''', '''''')  + ''', ' + 
  15516.             @bitmap_str   + ', ' + 
  15517.             convert(nvarchar(2), @identity_support)  + ',' +
  15518.             convert(nvarchar(2), @independent_agent) + ',N' +
  15519.             quotename(@distributor,'''') +   
  15520.             ' )}'
  15521.  
  15522.         -- Must add ver check cmd for each article since user can subscribe
  15523.         -- to just one article.    
  15524.         insert into #art_commands values (@artid, @ver_check_cmd)                        
  15525.         insert into #art_commands values (@artid, @replcmd)
  15526.  
  15527.         --
  15528.         -- If we are processing queued publications, insert another command
  15529.         -- to populate MSsubsciption_articles for this article
  15530.         --
  15531.         if (@is_queued = 1)
  15532.         begin
  15533.             select @cft_table = OBJECT_NAME(conflict_tableid) 
  15534.             from sysarticleupdates
  15535.             where artid = @artid and pubid = @pubid
  15536.  
  15537.             if (@cft_table IS NULL)
  15538.             begin
  15539.                 CLOSE hCsynctran_arts
  15540.                 DEALLOCATE hCsynctran_arts
  15541.                 raiserror('Debug: article %s in publication % should have valid conflict table', 
  15542.                     16, 1, @art_name, @publication)
  15543.                 return 1                
  15544.             end
  15545.  
  15546.             --
  15547.             -- add another command
  15548.             --
  15549.             select @replcmd = '{call sp_addqueued_artinfo (' + 
  15550.                 cast(@artid as nvarchar(10)) collate database_default + ', N' +
  15551.                 quotename(@art_name,'''') collate database_default + ', N' +                 
  15552.                 quotename(@@SERVERNAME,'''') collate database_default + ', N' +   
  15553.                 quotename(db_name(),'''') collate database_default + ', N' + 
  15554.                 quotename(@publication,'''') collate database_default + ', N' +  
  15555.                 quotename(@dest_table,'''') collate database_default + ', N' + 
  15556.                 quotename(@dest_owner,'''') collate database_default + ', N' +   
  15557.                 quotename(@cft_table,'''') collate database_default + ', ' +
  15558.                 master.dbo.fn_varbintohexstr(@columns) collate database_default + ' )}'
  15559.             
  15560.             -- Must add ver check cmd for each article since user can subscribe
  15561.             -- to just one article.    
  15562.             insert into #art_commands values (@artid, @ver_check_cmd)                        
  15563.             insert into #art_commands values (@artid, @replcmd)                        
  15564.         end
  15565.  
  15566.         FETCH hCsynctran_arts INTO @artid, @tabid, @dest_table, @dest_owner, @art_name, 
  15567.             @art_type, @filter_id, @columns
  15568.     end
  15569.  
  15570.     -- end SyncTran
  15571.     if @command_only = 0 
  15572.         select * from #art_commands order by id
  15573.     else
  15574.         select commands from #art_commands order by id
  15575.  
  15576.     CLOSE hCsynctran_arts
  15577.     DEALLOCATE hCsynctran_arts
  15578.  
  15579.     return 0
  15580. END
  15581. go
  15582.  
  15583. EXEC dbo.sp_MS_marksystemobject sp_MSget_synctran_commands
  15584. GO
  15585.  
  15586. raiserror('Creating procedure sp_script_synctran_commands', 0,1)
  15587. GO
  15588. CREATE PROCEDURE sp_script_synctran_commands(
  15589.     @publication sysname,    /* publication name */
  15590.     @article sysname = 'all'    /* article name, all means all article */
  15591. ) AS
  15592.     declare @retcode int
  15593.     exec @retcode = dbo.sp_MSget_synctran_commands 
  15594.         @publication = @publication,
  15595.         @article = @article,
  15596.         @command_only = 1
  15597.     if @retcode <> 0 or @@error <> 0
  15598.         return (1)
  15599.  
  15600. go
  15601.  
  15602. dump tran master with no_log
  15603. go
  15604.  
  15605. EXEC dbo.sp_MS_marksystemobject sp_script_synctran_commands
  15606. GO
  15607.  
  15608. print ''
  15609. print 'Creating procedure sp_MSaddpub_snapshot'
  15610. go
  15611. CREATE PROCEDURE sp_MSaddpub_snapshot (
  15612.     @publication sysname,    
  15613.     @freqtype  int = 4 ,                  /* 4== Daily */
  15614.     @freqinterval int  = 1,             /* Every day */
  15615.     @freqsubtype int =  4,                 /* Sub interval = Minute */
  15616.     @freqsubinterval int = 5,              /* Every five minutes */
  15617.     @freqrelativeinterval int = 1, 
  15618.     @freqrecurrencefactor int = 0, 
  15619.     @activestartdate int = 0,             /* 12:00 am - 11:59 pm */
  15620.     @activeenddate int =99991231 ,         /* No start date */    
  15621.     @activestarttimeofday int = 0,         
  15622.     @activeendtimeofday int = 235959,     /* No end time */       
  15623.     @newagentid int = 0 OUTPUT,
  15624.     @snapshot_job_name nvarchar(100) = null
  15625. ) AS
  15626.  
  15627.  
  15628.     SET NOCOUNT ON
  15629.  
  15630.     /*
  15631.     ** Declarations.
  15632.     */
  15633.     DECLARE @retcode            int
  15634.     DECLARE @distributor        sysname
  15635.     DECLARE @distribdb          sysname
  15636.     DECLARE @distproc           nvarchar (255)
  15637.     DECLARE @agentname          nvarchar(100)
  15638.     DECLARE @database           sysname
  15639.     DECLARE @newid              int
  15640.     DECLARE @mergepublish_bit   smallint
  15641.     DECLARE @centralpublish_bit int
  15642.     DECLARE @fFoundPublication  int
  15643.     DECLARE @agent_args         nvarchar(4000)
  15644.     DECLARE @snapshot_jobid     binary(16)
  15645.     DECLARE @dist_rpcname       sysname
  15646.     DECLARE @publication_type   int
  15647.     DECLARE @job_existing       bit
  15648.  
  15649.     /*
  15650.     ** Initializations
  15651.     */
  15652.     select @mergepublish_bit    = 4
  15653.     select @centralpublish_bit  = 1
  15654.     select @fFoundPublication   = 0
  15655.     if (@snapshot_job_name is null) or (@snapshot_job_name = N'')
  15656.     begin
  15657.         select @job_existing = 0
  15658.     end 
  15659.     else
  15660.     begin
  15661.         select @job_existing = 1
  15662.     end
  15663.  
  15664.     EXEC @retcode = dbo.sp_helppublication @publication, @fFoundPublication output
  15665.  
  15666.     IF @@ERROR <> 0 OR @retcode <> 0
  15667.     BEGIN
  15668.         RETURN (1)
  15669.     END
  15670.         
  15671.     IF @fFoundPublication = 0 
  15672.     BEGIN
  15673.         SELECT @newagentid = 0
  15674.         RETURN (0)
  15675.     END
  15676.  
  15677.         
  15678.     /* 
  15679.     ** Make sure the publication does not already have a agent.
  15680.     */
  15681.     IF EXISTS (SELECT * FROM syspublications WHERE name = @publication and snapshot_jobid <> NULL)
  15682.     BEGIN
  15683.         RAISERROR (14101, 11, -1, @publication)
  15684.         RETURN(1)
  15685.     END
  15686.  
  15687.     /* Get publication_type */
  15688.     SELECT @publication_type = repl_freq from syspublications WHERe name = @publication
  15689.     
  15690.     /*
  15691.     ** Get distributor information
  15692.     */
  15693.     EXEC @retcode = dbo.sp_helpdistributor @distributor = @distributor OUTPUT, 
  15694.         @distribdb = @distribdb OUTPUT,
  15695.         @rpcsrvname = @dist_rpcname OUTPUT
  15696.     IF @@error <> 0 OR @retcode <> 0 or @distributor IS NULL OR @distribdb IS NULL
  15697.     BEGIN
  15698.         RAISERROR (14071, 16, -1)
  15699.         RETURN (1)
  15700.     END
  15701.  
  15702.     SELECT @database = DB_NAME()
  15703.  
  15704.     SELECT @distproc = RTRIM(@dist_rpcname) + '.' + @distribdb + '.dbo.sp_MSadd_snapshot_agent'
  15705.     
  15706.     SELECT @agent_args = '-Publisher ' + QUOTENAME(@@SERVERNAME)
  15707.     SELECT @agent_args = @agent_args + ' -PublisherDB ' + QUOTENAME(@database)
  15708.     SELECT @agent_args = @agent_args + ' -Distributor ' + QUOTENAME(@distributor)
  15709.     SELECT @agent_args = @agent_args + ' -Publication ' + QUOTENAME(@publication)
  15710.  
  15711.     BEGIN TRAN
  15712.  
  15713.     EXECUTE @retcode = @distproc 
  15714.         @name = @snapshot_job_name,
  15715.         @publisher = @@SERVERNAME,
  15716.         @publisher_db = @database,
  15717.         @publication = @publication,  
  15718.         @publication_type = @publication_type,
  15719.         @local_job = 1,  
  15720.  
  15721.         @freqtype = @freqtype, 
  15722.         @freqinterval = @freqinterval, 
  15723.         @freqsubtype = @freqsubtype, 
  15724.         @freqsubinterval = @freqsubinterval, 
  15725.         @freqrelativeinterval = @freqrelativeinterval, 
  15726.         @freqrecurrencefactor = @freqrecurrencefactor, 
  15727.         @activestartdate = @activestartdate, 
  15728.         @activeenddate = @activeenddate, 
  15729.         @activestarttimeofday = @activestarttimeofday, 
  15730.         @activeendtimeofday =  @activeendtimeofday,
  15731.         @command = @agent_args,
  15732.         @snapshot_jobid = @snapshot_jobid OUTPUT,
  15733.         @job_existing = @job_existing
  15734.   
  15735.    IF @@ERROR <> 0 or @retcode <> 0
  15736.         GOTO UNDO
  15737.  
  15738.     -- Legacy, use non zero taskid to indicate agent already created at the distributor.
  15739.     UPDATE syspublications set snapshot_jobid =  @snapshot_jobid
  15740.         WHERE name =  @publication 
  15741.  
  15742.     IF @@ERROR <> 0 
  15743.         GOTO UNDO
  15744.  
  15745.     -- This is the output parameter to indicate agent created.
  15746.     SELECT  @newagentid = 1
  15747.  
  15748.     COMMIT TRAN
  15749.  
  15750.     return (0)  
  15751.     
  15752. UNDO:
  15753.     if @@TRANCOUNT = 1
  15754.         ROLLBACK TRAN
  15755.     else
  15756.         COMMIT TRAN
  15757.     return(1)
  15758. GO
  15759.  
  15760. EXEC dbo.sp_MS_marksystemobject sp_MSaddpub_snapshot
  15761. GO
  15762.  
  15763. dump tran master with no_log
  15764. GO
  15765.  
  15766. /*
  15767. ** SyncTran support procs
  15768. */
  15769.  
  15770. print ''
  15771. print 'Creating procedure sp_MSis_pk_col'
  15772. go
  15773. create proc sp_MSis_pk_col @source_table sysname, @colname sysname, @indid int
  15774. as
  15775. begin
  15776.  
  15777.     declare @indkey int
  15778.     select @indkey = 1
  15779.  
  15780.     while @indkey < 16 and index_col(@source_table, @indid, @indkey) is not null
  15781.     begin
  15782.         if index_col(@source_table, @indid, @indkey) = @colname
  15783.             return (1)
  15784.  
  15785.         select @indkey = @indkey + 1
  15786.     end
  15787.  
  15788.     return (0)
  15789. end
  15790. GO
  15791. EXEC dbo.sp_MS_marksystemobject sp_MSis_pk_col
  15792. GO
  15793.  
  15794. print ''
  15795. print 'Creating procedure sp_MSmark_proc_norepl'
  15796. go
  15797.  
  15798. create procedure sp_MSmark_proc_norepl
  15799.     @procname nvarchar(517)
  15800. as
  15801.     set nocount on
  15802.  
  15803.     -- CHECK PERMISSIONS (MUST BE DBO) --
  15804.     if not (is_member('db_owner')=1 or is_srvrolemember('sysadmin') = 1) 
  15805.     begin
  15806.         raiserror(20521,0,1)
  15807.         return 1
  15808.     end
  15809.  
  15810.     -- CHECK THE OBJECT NAME --
  15811.     if object_id(@procname, 'local') is null
  15812.     begin
  15813.         raiserror(20522,0,1,@procname)
  15814.         return 1
  15815.     end
  15816.  
  15817.     -- DO THE UPDATE --
  15818.     begin tran
  15819.     exec dbo.sp_replupdateschema @procname
  15820.     update sysobjects set replinfo = replinfo | 0x40
  15821.                         where id = object_id(@procname, 'local')
  15822.     exec dbo.sp_replupdateschema @procname
  15823.     commit tran
  15824.     return @@error 
  15825. go
  15826.  
  15827. EXEC dbo.sp_MS_marksystemobject sp_MSmark_proc_norepl
  15828. GO
  15829.  
  15830. create procedure sp_MSdrop_expired_subscription
  15831. AS
  15832. /*
  15833. ** This stored procedure is to periodically check the status of all the subscriptions 
  15834. ** of every merge publication. If any of them is out-of-date, i.e., has lost contact
  15835. ** with publisher for a certain length of time, we can declare the death of that replica
  15836. ** and cleanup their traces at the publisher side
  15837. */
  15838. declare @independent_agent  bit
  15839. declare @article            sysname
  15840. declare @publication        sysname
  15841. declare @pubid              int
  15842. declare @artid              int
  15843. declare @publisher          sysname
  15844. declare @subscriber         sysname
  15845. declare @subscriber_id      smallint
  15846. declare @subscriber_db      sysname
  15847. declare @publisher_db       sysname
  15848. declare @out_of_date        int
  15849. declare @distributor        sysname
  15850. declare @distribdb          sysname
  15851. declare @retention          int  -- in days         
  15852. declare @retcode            smallint
  15853. declare @distproc           nvarchar(255)
  15854. declare @localproc          nvarchar(255)
  15855. declare @msg                nvarchar(255)
  15856. declare @open_cursor        nvarchar(400)
  15857.  
  15858.     /*
  15859.     ** Security Check
  15860.     */
  15861. EXEC @retcode = dbo.sp_MSreplcheck_publish
  15862.     IF @@ERROR <> 0 or @retcode <> 0
  15863.         return (1)
  15864.  
  15865.     /*
  15866.     ** Get distribution server information for remote RPC call.
  15867.     */
  15868. EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  15869.      @distribdb   = @distribdb OUTPUT
  15870. IF @@ERROR <> 0 or @retcode <> 0
  15871.     BEGIN
  15872.         RAISERROR (20036, 16, -1)
  15873.         return (1)
  15874.     END
  15875.  
  15876.     
  15877. SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MShelp_subscription_status '
  15878. select @publisher = @@SERVERNAME
  15879. select @publisher_db = db_name()
  15880.  
  15881. declare PC CURSOR LOCAL FAST_FORWARD for select DISTINCT name, pubid, independent_agent, retention from syspublications p
  15882.     open PC
  15883.     fetch PC into @publication, @pubid, @independent_agent, @retention
  15884.     WHILE (@@fetch_status <> -1)
  15885.         BEGIN
  15886.             -- Don't do anything if the retention is zero, this means
  15887.             -- subscriptions to the publication will never expire
  15888.             IF @retention = 0
  15889.             BEGIN
  15890.                 GOTO ZERO_RETENTION
  15891.             END
  15892.             declare SC CURSOR LOCAL FAST_FORWARD for select s.srvid, s.dest_db, a.name from syssubscriptions s, sysextendedarticlesview a 
  15893.                 where a.pubid= @pubid and s.artid = a.artid and s.srvid<>-1 
  15894.                 for read only
  15895.             open SC
  15896.             fetch SC into @subscriber_id, @subscriber_db, @article
  15897.             WHILE (@@fetch_status <> -1)
  15898.                 BEGIN
  15899.                     select @subscriber=srvname from master..sysservers where srvid=@subscriber_id
  15900.                     exec @retcode = @distproc @publisher = @publisher, 
  15901.                                     @publisher_db = @publisher_db, 
  15902.                                     @publication = @publication, 
  15903.                                     @subscriber = @subscriber, 
  15904.                                     @subscriber_db = @subscriber_db,
  15905.                                     @retention = @retention,
  15906.                                     @out_of_date = @out_of_date OUTPUT,
  15907.                                     @independent_agent = @independent_agent
  15908.                     if @retcode<>0 or @@ERROR<>0 
  15909.                         begin
  15910.                             close SC
  15911.                             deallocate SC
  15912.                             close PC
  15913.                             deallocate PC
  15914.                             return (1)
  15915.                         end
  15916.                     IF (@out_of_date = 1)
  15917.                         begin
  15918.                             exec @retcode = dbo.sp_dropsubscription   -- publisher_db.dbo.sp_dropsubscription
  15919.                                 @publication = @publication,
  15920.                                 @article = @article,
  15921.                                 @subscriber = @subscriber,
  15922.                                 @destination_db = @subscriber_db,
  15923.                                 @reserved = 'internal'
  15924.                             if @retcode <>0 or @@ERROR<>0
  15925.                                 begin
  15926.                                     close SC
  15927.                                     deallocate SC
  15928.                                     close PC
  15929.                                     deallocate PC
  15930.                                     return (1)
  15931.                                 end
  15932.                             raiserror(14157, 10, -1, @subscriber, @publication) 
  15933.                         end
  15934.                     fetch SC into @subscriber_id, @subscriber_db, @article
  15935.                 END
  15936.             CLOSE SC
  15937.             DEALLOCATE SC
  15938.     ZERO_RETENTION:
  15939.             fetch PC into @publication, @pubid, @independent_agent, @retention
  15940.         END
  15941.     CLOSE PC
  15942.     DEALLOCATE PC
  15943.  
  15944. GO
  15945. EXEC dbo.sp_MS_marksystemobject sp_MSdrop_expired_subscription
  15946. go
  15947.  
  15948.  
  15949. -- synctran supporting procs
  15950. raiserror('Creating procedure sp_MSscript_validate_subscription', 0,1)
  15951. go
  15952. create procedure sp_MSscript_validate_subscription (
  15953.     @publication sysname,
  15954.     @article sysname)
  15955. as
  15956. BEGIN
  15957.     declare @cmd          nvarchar(4000)
  15958.     declare @pubid int
  15959.     declare @artid int
  15960.     select @pubid = pubid from syspublications where name = @publication
  15961.     select @artid = artid from sysarticles where pubid = @pubid and name = @article
  15962.  
  15963.     select @cmd = N'
  15964.     ' + N'--
  15965.     ' + N'-- Check for subscription validation
  15966.     ' + N'--
  15967.     exec @retcode = dbo.sp_MSvalidate_subscription @orig_server, @orig_db, '
  15968.             + convert(nvarchar(10), @artid) + N'
  15969.     if (@retcode != 0 or @@error != 0)
  15970.         return -1'
  15971.  
  15972.     insert into #proctext(procedure_text) values(@cmd)
  15973.     return 0        
  15974. END                    
  15975. go
  15976. EXEC dbo.sp_MS_marksystemobject sp_MSscript_validate_subscription
  15977. GO
  15978.  
  15979.  
  15980. -- synctran supporting procs
  15981. raiserror('Creating procedure sp_MSvalidate_subscription', 0,1)
  15982. go
  15983. create procedure sp_MSvalidate_subscription
  15984.     @subscriber sysname,
  15985.     @subscriber_db sysname,
  15986.     @artid int
  15987. as
  15988.  
  15989.     declare @srvid smallint
  15990.     select @srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber) collate database_default
  15991.     if not exists (select * from syssubscriptions where artid = @artid and 
  15992.         srvid = @srvid and dest_db = @subscriber_db)
  15993.     begin
  15994.         --  The subscription has been dropped from the publisher. Please run sp_subscription_cleanup to cleanup the triggers.
  15995.         exec sp_MSreplraiserror 21161
  15996.         return -1
  15997.     end                    
  15998. go
  15999. EXEC dbo.sp_MS_marksystemobject sp_MSvalidate_subscription
  16000. GO
  16001.  
  16002.  
  16003. raiserror('Creating procedure sp_MSscript_insert_statement', 0,1)
  16004. go
  16005. create procedure sp_MSscript_insert_statement(
  16006.     @objid int,
  16007.     @columns binary(32),
  16008.     @identity_insert bit = 0,
  16009.     @queued_pub bit = 0
  16010.     )
  16011. as
  16012. BEGIN
  16013.     declare @cmd          nvarchar(4000)
  16014.     declare @qualname     nvarchar(512)
  16015.     declare @colname      sysname
  16016.     declare @ccoltype     sysname
  16017.     declare @this_col     int
  16018.     declare @rc           int
  16019.     declare @num_col      int
  16020.     declare @column_string nvarchar(4000)
  16021.             ,@var_string nvarchar(4000)
  16022.     
  16023.     
  16024.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  16025.  
  16026.     --
  16027.     -- start scripting
  16028.     --
  16029.     select @cmd = N'
  16030.     ' + N'--
  16031.     ' + N'-- detection/conflict resolution stage
  16032.     ' + N'--'
  16033.     
  16034.     if (@queued_pub = 1)
  16035.     begin
  16036.         select @cmd = @cmd + N'
  16037.     if (@execution_mode = @QPubWins)
  16038.         save tran cftpass'
  16039.     end
  16040.     insert into #proctext(procedure_text) values( @cmd) 
  16041.     
  16042.     --
  16043.     -- set indentity_insert on
  16044.     --
  16045.     if @identity_insert = 1
  16046.     begin
  16047.         -- Only to call set if identity is not marked for 'not for repl'
  16048.         -- This is to avoid security failure of 'SET' for PAL users
  16049.         if not exists (select * from syscolumns where id = @objid and
  16050.             ColumnProperty(id, name, 'IsIdNotForRepl') = 1)
  16051.         begin
  16052.             select @cmd = N'
  16053.     set identity_insert ' + @qualname + ' on'
  16054.             insert into #proctext(procedure_text) values( @cmd )
  16055.         end
  16056.     end
  16057.  
  16058.     --
  16059.     -- prepare the insert statement now
  16060.     --
  16061.     select @cmd = N'
  16062.     insert into ' + @qualname + N'( '
  16063.     insert into #proctext(procedure_text) values( @cmd )
  16064.     -- Generate strings for col names and variables
  16065.     select @num_col = 0
  16066.     select @cmd = N''
  16067.  
  16068.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  16069.     select colid from syscolumns where id = @objid order by colid asc
  16070.  
  16071.     OPEN hCColid
  16072.  
  16073.     FETCH hCColid INTO @this_col
  16074.  
  16075.     WHILE (@@fetch_status != -1)
  16076.     begin
  16077.         exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output
  16078.         if @rc = 0  and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  16079.         begin
  16080.             if rtrim(@ccoltype) not like N'timestamp' and 
  16081.                 not (ColumnProperty(@objid, @colname, 'IsIdentity') = 1 and 
  16082.                     @identity_insert = 0)
  16083.             begin
  16084.                 select @num_col = @num_col + 1
  16085.                 if @num_col > 1
  16086.                     select @cmd = @cmd + N', '
  16087.                 select @cmd = @cmd + QUOTENAME(@colname)            
  16088.                 exec dbo.sp_MSflush_command @cmd output, 1
  16089.             end
  16090.         end
  16091.         FETCH hCColid INTO @this_col
  16092.     end
  16093.     CLOSE hCColid
  16094.  
  16095.     -- Script end of colmn names
  16096.     select @cmd = N' )'
  16097.     insert into #proctext(procedure_text) values( @cmd )
  16098.  
  16099.     
  16100.     -- Script column value string
  16101.     if @num_col > 0
  16102.     begin
  16103.         select @cmd = N'
  16104.     values ( '
  16105.         insert into #proctext(procedure_text) values( @cmd )
  16106.         -- Script column value string
  16107.         select @num_col = 0
  16108.         select @cmd = N''
  16109.  
  16110.         OPEN hCColid
  16111.  
  16112.         FETCH hCColid INTO @this_col
  16113.  
  16114.         WHILE (@@fetch_status != -1)
  16115.         begin
  16116.             exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output
  16117.             if @rc = 0  and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  16118.             begin
  16119.                 if rtrim(@ccoltype) not like N'timestamp' and 
  16120.                     not (ColumnProperty(@objid, @colname, 'IsIdentity') = 1 and 
  16121.                         @identity_insert = 0)
  16122.                 begin
  16123.                     select @num_col = @num_col + 1
  16124.                     if @num_col > 1
  16125.                         select @cmd = @cmd + N', '
  16126.                     select @cmd = @cmd + N'@c' + cast(@this_col as nvarchar(4))                
  16127.                     exec dbo.sp_MSflush_command @cmd output, 1
  16128.                 end
  16129.             end
  16130.             FETCH hCColid INTO @this_col
  16131.         end
  16132.         CLOSE hCColid
  16133.         
  16134.         -- Script end of column value string
  16135.         select @cmd = N' )
  16136.     '
  16137.         insert into #proctext(procedure_text) values( @cmd )
  16138.     end
  16139.     else
  16140.     begin
  16141.         -- This is to set @@rowcount.
  16142.         insert into #proctext(procedure_text) values( N' 
  16143.     select @retcode = @retcode')
  16144.     end
  16145.     
  16146.     --
  16147.     -- set the rowcount and error
  16148.     --
  16149.     select @cmd = N'
  16150.     select @rowcount = @@ROWCOUNT, @error = @@ERROR 
  16151.     '
  16152.     insert into #proctext(procedure_text) values( @cmd )
  16153.  
  16154.     --
  16155.     -- set indentity_insert off
  16156.     --
  16157.     if @identity_insert = 1
  16158.     begin
  16159.         -- Only to call set if identity is not marked for 'not for repl'
  16160.         -- This is to avoid security failure of 'SET' for PAL users
  16161.         if not exists (select * from syscolumns where id = @objid and
  16162.             ColumnProperty(id, name, 'IsIdNotForRepl') = 1)
  16163.         begin
  16164.             select @cmd = N'
  16165.     set identity_insert ' + @qualname + ' off'
  16166.             insert into #proctext(procedure_text) values( @cmd )
  16167.         end
  16168.     end
  16169.  
  16170.  
  16171.     if (@queued_pub = 1)
  16172.     begin
  16173.         select @cmd = N'
  16174.     if (@execution_mode = @QPubWins)
  16175.         rollback tran cftpass'
  16176.         insert into #proctext(procedure_text) values( @cmd )
  16177.     end
  16178.     
  16179.     --
  16180.     -- all done 
  16181.     -- 
  16182.     return 0
  16183. END
  16184. go
  16185.  
  16186. EXEC dbo.sp_MS_marksystemobject sp_MSscript_insert_statement
  16187. GO
  16188.  
  16189. --
  16190. -- proc to generate subscriber wins resolution code block
  16191. -- for insert proc used for synctran/queued
  16192. --
  16193. raiserror('Creating procedure sp_MSscript_insert_subwins', 0,1)
  16194. go
  16195. create procedure sp_MSscript_insert_subwins (
  16196.     @publication sysname,
  16197.     @article     sysname, 
  16198.     @objid int,
  16199.     @columns binary(32),
  16200.     @identity_insert bit)
  16201. AS
  16202. BEGIN
  16203.     declare @cmd nvarchar(4000)
  16204.             ,@qualname nvarchar(512)
  16205.             ,@column_string nvarchar(4000)
  16206.             ,@var_string nvarchar(4000)
  16207.             ,@colname      sysname
  16208.             ,@ccoltype     sysname
  16209.             ,@this_col     int
  16210.             ,@rc           int
  16211.             ,@num_col      int
  16212.  
  16213.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  16214.  
  16215.     select @cmd = N'
  16216.     if (@error in (0, 547, 2627) and @execution_mode = @QSubWins)
  16217.     begin
  16218.         ' + N'--
  16219.         ' + N'-- Subscriber Wins resolution
  16220.         ' + N'--
  16221.         if (@rowcount = 1 and @error = 0)
  16222.         begin'
  16223.  
  16224.     insert into #proctext(procedure_text) values( @cmd )
  16225.  
  16226.     select @cmd = N'
  16227.             ' + N'--
  16228.             ' + N'-- No conflict for this command
  16229.             ' + N'-- do nothing
  16230.             ' + N'-- will remove this code block later 
  16231.             ' + N'-- for optimization
  16232.             ' + N'--
  16233.             select @retcode = 0
  16234.         end'
  16235.  
  16236.     insert into #proctext(procedure_text) values( @cmd )
  16237.  
  16238.     select @cmd = N'        
  16239.         else if (@rowcount = 0 and @error in (547, 2627))
  16240.         begin
  16241.             ' + N'--
  16242.             ' + N'-- Conflict for this command
  16243.             ' + N'-- Row already exists
  16244.             ' + N'-- delete and insert row with Queue values
  16245.             ' + N'-- '
  16246.     insert into #proctext(procedure_text) values( @cmd )
  16247.  
  16248.     --
  16249.     -- script delete
  16250.     --
  16251.     select @cmd = N'
  16252.             delete ' + @qualname 
  16253.     insert into #proctext(procedure_text) values( @cmd )
  16254.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0
  16255.  
  16256.     --
  16257.     -- script the insert assignment
  16258.     --
  16259.     select @num_col = 0
  16260.     create table #worktab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  16261.     create table #worktab2 ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  16262.  
  16263.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  16264.     select colid from syscolumns where id = @objid order by colid asc
  16265.  
  16266.     OPEN hCColid
  16267.     FETCH hCColid INTO @this_col
  16268.     WHILE (@@fetch_status != -1)
  16269.     begin
  16270.         exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output
  16271.         if @rc = 0  and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  16272.         begin
  16273.             if rtrim(@ccoltype) not like N'timestamp' 
  16274.             begin
  16275.                 select @num_col = @num_col + 1
  16276.                 select @column_string = QUOTENAME(@colname)
  16277.                 select @var_string = N'@c' + cast(@this_col as nvarchar(4))
  16278.                 
  16279.                 if (@num_col > 1)
  16280.                 begin
  16281.                     select @column_string = N', ' + @column_string
  16282.                     select @var_string = N', ' +@var_string 
  16283.                 end
  16284.  
  16285.                 insert into #worktab(procedure_text) values( @column_string )                
  16286.                 insert into #worktab2(procedure_text) values( @var_string )                
  16287.                 
  16288.             end
  16289.         end
  16290.         FETCH hCColid INTO @this_col
  16291.     end
  16292.     CLOSE hCColid
  16293.     DEALLOCATE hCColid
  16294.  
  16295.     if (@num_col > 0)
  16296.     begin
  16297.         if (@identity_insert = 1)
  16298.         begin
  16299.             -- Only to call set if identity is not marked for 'not for repl'
  16300.             -- This is to avoid security failure of 'SET' for PAL users
  16301.             if not exists (select * from syscolumns where id = @objid and
  16302.                 ColumnProperty(id, name, 'IsIdNotForRepl') = 1)
  16303.             begin
  16304.                 select @cmd = N'
  16305.             set identity_insert ' + @qualname + N' on '
  16306.                 insert into #proctext(procedure_text) values( @cmd )
  16307.             end
  16308.         end
  16309.  
  16310.         select @cmd = N'
  16311.             insert into ' + @qualname + N'( '
  16312.         insert into #proctext(procedure_text) values( @cmd )
  16313.         insert into #proctext(procedure_text) 
  16314.             select procedure_text from #worktab order by c1 asc
  16315.         select @cmd = N' )
  16316.             values ( '
  16317.         insert into #proctext(procedure_text) values( @cmd )
  16318.         insert into #proctext(procedure_text) 
  16319.             select procedure_text from #worktab2 order by c1 asc
  16320.         select @cmd = N' )'
  16321.         insert into #proctext(procedure_text) values( @cmd )
  16322.  
  16323.         if (@identity_insert = 1)
  16324.         begin
  16325.             -- Only to call set if identity is not marked for 'not for repl'
  16326.             -- This is to avoid security failure of 'SET' for PAL users
  16327.             if not exists (select * from syscolumns where id = @objid and
  16328.                 ColumnProperty(id, name, 'IsIdNotForRepl') = 1)
  16329.             begin
  16330.                 select @cmd = N'
  16331.             set identity_insert ' + @qualname + N' off '
  16332.                 insert into #proctext(procedure_text) values( @cmd )
  16333.             end
  16334.         end
  16335.     end
  16336.     
  16337.     select @cmd = N'
  16338.             if (@@error != 0 or @retcode != 0)
  16339.                 return -1
  16340.         end
  16341.         else
  16342.             return -1
  16343.     end'
  16344.     insert into #proctext(procedure_text) values( @cmd )
  16345.  
  16346.     --
  16347.     -- all done
  16348.     --
  16349.     drop table #worktab
  16350.     drop table #worktab2
  16351.     return 0
  16352. END
  16353. go
  16354.  
  16355. EXEC dbo.sp_MS_marksystemobject sp_MSscript_insert_subwins
  16356. GO
  16357.  
  16358. --
  16359. -- proc to test if we need to turn on identity insert
  16360. --
  16361. raiserror('Creating procedure sp_MSis_identity_insert', 0,1)
  16362. go
  16363. create procedure sp_MSis_identity_insert
  16364. @publication sysname,
  16365. @article sysname,
  16366. @identity_insert bit output,
  16367. @artid int = NULL    -- If pass in @artid, you don't need to pass in 
  16368.                     -- @publication and @article
  16369. as
  16370.     declare @pubid int, @source_objid int
  16371.         ,@columns      binary(32)
  16372.     
  16373.     select @identity_insert = 0
  16374.  
  16375.     -- Get @artid if not there
  16376.     -- If the publication is not queued
  16377.     if @artid is null
  16378.     begin
  16379.         select @pubid = pubid from syspublications where name = @publication
  16380.         select @artid = artid from sysarticles where
  16381.             pubid = @pubid and
  16382.             name = @article
  16383.     end        
  16384.  
  16385.     -- Get @pubid from @artid
  16386.     if @pubid is null
  16387.         select @pubid = pubid    from sysarticles where 
  16388.             artid = @artid
  16389.  
  16390.     if exists (select * from syspublications where
  16391.         pubid = @pubid and
  16392.         allow_queued_tran = 1)
  16393.     begin
  16394.         select @source_objid = objid, @columns = columns from sysarticles where
  16395.             artid = @artid and
  16396.             OBJECTPROPERTY(objid, 'tablehasidentity') = 1
  16397.         if @source_objid is not null
  16398.         begin
  16399.             declare @colid smallint, @in_partition int
  16400.             select @colid = colid from syscolumns where id = @source_objid and
  16401.                 COLUMNPROPERTY(@source_objid, name, 'IsIdentity') = 1
  16402.             exec @in_partition = sp_isarticlecolbitset @colid, @columns
  16403.             if @in_partition = 1
  16404.                 select @identity_insert = 1
  16405.         end
  16406.     end
  16407.     return @identity_insert
  16408. go
  16409.  
  16410. EXEC dbo.sp_MS_marksystemobject sp_MSis_identity_insert
  16411. GO
  16412.  
  16413. --
  16414. -- proc that scripts the sending of a compensating command
  16415. -- used by the compensating code generation SPs
  16416. --
  16417. raiserror('Creating procedure sp_MSscript_compensating_send', 0,1)
  16418. go
  16419. create procedure sp_MSscript_compensating_send (
  16420.     @pubid int,
  16421.     @artid int,
  16422.     @cmdstate int = 0,
  16423.     @setprefix bit = 1)
  16424. AS
  16425. BEGIN
  16426.     declare @cmd nvarchar(4000)
  16427.     
  16428.     select @cmd = N'
  16429.             ' + N'--
  16430.             ' + N'-- sending of compensating command
  16431.             ' + N'--'
  16432.     insert into #proctext(procedure_text) values( @cmd )
  16433.  
  16434.     select @cmd = N'
  16435.             exec @retcode = dbo.sp_MSadd_compensating_cmd
  16436.                 @orig_srv = @orig_server
  16437.                 ,@orig_db = @orig_db
  16438.                 ,@command = @cmd
  16439.                 ,@article_id = ' + CAST(@artid as nvarchar(4)) + N'
  16440.                 ,@publication_id = ' + CAST(@pubid as nvarchar(4)) + N'
  16441.                 ,@cmdstate = ' + CAST(@cmdstate as nvarchar(4)) + N'
  16442.                 ,@mode = 0
  16443.                 ,@setprefix = ' + CAST(@setprefix as nvarchar(4))
  16444.     insert into #proctext(procedure_text) values( @cmd )
  16445.  
  16446.     select @cmd = N'
  16447.             if (@@error != 0 or @retcode != 0)
  16448.                 return -1'
  16449.     insert into #proctext(procedure_text) values( @cmd )
  16450.  
  16451.     --
  16452.     -- all done
  16453.     --
  16454.     return 0    
  16455. END
  16456. go
  16457.  
  16458. EXEC dbo.sp_MS_marksystemobject sp_MSscript_compensating_send
  16459. GO
  16460.  
  16461. --
  16462. -- proc to generate publisher wins resolution code block
  16463. -- for insert proc used for synctran/queued
  16464. --
  16465. raiserror('Creating procedure sp_MSscript_insert_pubwins', 0,1)
  16466. go
  16467. create procedure sp_MSscript_insert_pubwins (
  16468.     @publication sysname,
  16469.     @article     sysname, 
  16470.     @objid int,
  16471.     @columns binary(32) )
  16472. AS
  16473. BEGIN
  16474.     declare @cmd nvarchar(4000)
  16475.             ,@artid int
  16476.             ,@pubid int
  16477.             ,@dest_table sysname
  16478.             ,@dest_owner nvarchar(260)
  16479.             ,@colname      sysname
  16480.             ,@ccoltype     sysname
  16481.             ,@this_col     int
  16482.             ,@rc           int
  16483.             ,@num_col      int
  16484.             ,@qualname nvarchar(512)
  16485.             ,@cast_str nvarchar(1000)
  16486.             ,@decl_str nvarchar(2000)
  16487.             ,@assign_str nvarchar(4000)
  16488.             ,@typestring nvarchar(100)
  16489.             ,@exec_str nvarchar(1000)
  16490.  
  16491.     --
  16492.     -- initialize the vars we will use
  16493.     --
  16494.     select @pubid = pubid from syspublications where name = @publication
  16495.     select @artid = artid, @dest_table = dest_table, @dest_owner = dest_owner
  16496.     from sysarticles where name = @article and pubid = @pubid
  16497.     select @dest_owner = case when (@dest_owner IS NULL) then N''
  16498.                 else quotename(@dest_owner) + N'.' end
  16499.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  16500.                 
  16501.     --
  16502.     -- start script generation
  16503.     --
  16504.     select @cmd = N'
  16505.     else if (@error in (0, 547, 2627) and @execution_mode = @QPubWins)
  16506.     begin
  16507.         ' + N'--
  16508.         ' + N'-- Publisher Wins resolution
  16509.         ' + N'-- Find where we have to generate compensating action
  16510.         ' + N'--
  16511.         if (@rowcount = 1 and @error = 0)
  16512.         begin'
  16513.     insert into #proctext(procedure_text) values( @cmd )
  16514.  
  16515.     select @cmd = N'
  16516.             ' + N'--
  16517.             ' + N'-- No conflict for this command
  16518.             ' + N'-- Row does not exist
  16519.             ' + N'-- Generate delete compensating action
  16520.             ' + N'--
  16521.             select @cftcase = 23'
  16522.     insert into #proctext(procedure_text) values( @cmd )
  16523.  
  16524.     --
  16525.     -- Continue with scripting
  16526.     --
  16527.     select @cmd = N'
  16528.         end
  16529.         else if (@rowcount = 0 and @error in (547, 2627))
  16530.         begin
  16531.             ' + N'--
  16532.             ' + N'-- conflict for this command
  16533.             ' + N'-- Row already exists
  16534.             ' + N'-- generate update compensating action
  16535.             ' + N'-- DELETE compensating command + INSERT compensating command
  16536.             ' + N'--            
  16537.             select @cftcase = 21'
  16538.     insert into #proctext(procedure_text) values( @cmd )
  16539.  
  16540.     --
  16541.     -- continue with scripting
  16542.     --            
  16543.     select @cmd = N'        
  16544.         end
  16545.         else
  16546.             return -1
  16547.  
  16548.         ' + N'--
  16549.         ' + N'-- generate compensating command according to the cases
  16550.         ' + N'--'
  16551.     insert into #proctext(procedure_text) values( @cmd )
  16552.  
  16553.     select @cmd = N'
  16554.         if (@cftcase in (21,23))
  16555.         begin
  16556.             ' + N'--
  16557.             ' + N'-- delete compensating command
  16558.             ' + N'--'
  16559.     insert into #proctext(procedure_text) values( @cmd )
  16560.     
  16561.     --
  16562.     -- Generate the delete compensating code
  16563.     --
  16564.     select @cmd = N'
  16565.             select @cmd = ''DELETE ' + master.dbo.fn_MSgensqescstr(@dest_owner) collate database_default 
  16566.         + quotename(master.dbo.fn_MSgensqescstr(@dest_table) collate database_default) + N' '' + '
  16567.     insert into #proctext(procedure_text) values( @cmd )
  16568.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'qcft_comp', NULL, 0, 'ins'
  16569.     exec sp_MSscript_compensating_send @pubid, @artid, 0, 1
  16570.  
  16571.     select @cmd = N'
  16572.         end
  16573.  
  16574.         if (@cftcase = 21)
  16575.         begin
  16576.             ' + N'--
  16577.             ' + N'-- insert compensating command
  16578.             ' + N'--'
  16579.     insert into #proctext(procedure_text) values( @cmd )
  16580.  
  16581.     --
  16582.     -- generate the compensating insert command
  16583.     --
  16584.     exec dbo.sp_MSscript_compensating_insert @publication, @article, @objid, @columns, 0
  16585.  
  16586.     --
  16587.     -- continue with scripting
  16588.     --            
  16589.     select @cmd = N'        
  16590.         end
  16591.     end'
  16592.     insert into #proctext(procedure_text) values( @cmd )
  16593.  
  16594.     --
  16595.     -- all done
  16596.     --
  16597.     return 0    
  16598. END
  16599. go
  16600.  
  16601. EXEC dbo.sp_MS_marksystemobject sp_MSscript_insert_pubwins
  16602. GO
  16603.  
  16604.  
  16605.  
  16606. raiserror('Creating procedure sp_MSscript_update_statement', 0,1)
  16607. go
  16608. create procedure sp_MSscript_update_statement (
  16609.     @publication sysname,
  16610.     @article     sysname, 
  16611.     @objid int,
  16612.     @columns binary(32),
  16613.     @queued_pub bit = 0
  16614. )
  16615. as
  16616. BEGIN
  16617.     declare @cmd            nvarchar(4000)
  16618.             ,@cmd2            nvarchar(4000)
  16619.             ,@qualname        nvarchar(512)
  16620.             ,@colname        sysname
  16621.             ,@typestring    nvarchar(4000)
  16622.             ,@spacer        nvarchar(1)
  16623.             ,@ccoltype        sysname
  16624.             ,@this_col        int
  16625.             ,@rc            int
  16626.             ,@column        nvarchar(4000)
  16627.             ,@num_col        int
  16628.  
  16629.             ,@art_col        int -- position in the article partition.
  16630.             ,@isset            int
  16631.             ,@timestamp_subscribed bit
  16632.             ,@pubid            int
  16633.  
  16634.     select @pubid = pubid from syspublications where name = @publication
  16635.  
  16636.     if exists (select * from sysarticles where pubid = @pubid and
  16637.         name = @article and
  16638.         status & 32 <> 0)
  16639.         select @timestamp_subscribed = 1
  16640.     else
  16641.         select @timestamp_subscribed = 0
  16642.     
  16643.     --
  16644.     -- Start scripting
  16645.     --
  16646.     select @cmd = N'
  16647.     ' + N'--
  16648.     ' + N'-- detection/conflict resolution stage
  16649.     ' + N'--'
  16650.     
  16651.     if (@queued_pub = 1)
  16652.     begin
  16653.         select @cmd = @cmd + N'
  16654.     if (@execution_mode = @QPubWins)
  16655.         save tran cftpass
  16656.     '
  16657.     end
  16658.     insert into #proctext(procedure_text) values(@cmd)
  16659.     
  16660.     --
  16661.     -- Generate the update statement
  16662.     --
  16663.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  16664.     select @cmd2 = N'
  16665.     update ' + @qualname + N' set
  16666.     '
  16667.  
  16668.     select @spacer = N' 
  16669.         '
  16670.     select @cmd = N''
  16671.     exec dbo.sp_MSpad_command @cmd output, 8
  16672.     
  16673.     select @num_col = 0
  16674.     select @art_col = 0
  16675.  
  16676.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  16677.     select colid from syscolumns where id = @objid order by colid asc
  16678.  
  16679.     OPEN hCColid
  16680.     FETCH hCColid INTO @this_col
  16681.     WHILE (@@fetch_status <> -1)
  16682.     begin
  16683.         -- Get the ordinal of the article partition or not.
  16684.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  16685.         if @isset = 0
  16686.         begin
  16687.             -- Special handling of a timestamp col in a queued tran publication
  16688.             -- See sp_helparticlecolumns : xtype 189 is timestamp
  16689.             if ((@timestamp_subscribed = 1) and 
  16690.                     exists ( select * from dbo.syscolumns where id = @objid and colid = @this_col and xtype = 189))
  16691.                 select @art_col = @art_col + 1
  16692.         end
  16693.         else
  16694.             select @art_col = @art_col + 1
  16695.  
  16696.         exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output
  16697.         if @rc = 0 and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  16698.         begin
  16699.             if rtrim(@ccoltype) not like N'timestamp' and ColumnProperty(@objid, @colname, 'IsIdentity') != 1
  16700.             begin
  16701.                 if @cmd2 is not null
  16702.                 begin
  16703.                     exec dbo.sp_MSflush_command @cmd2 output, 1, 8
  16704.                     select @cmd2 = null
  16705.                 end
  16706.  
  16707.                 select @num_col = @num_col + 1
  16708.                 -- Optimization:
  16709.                 -- Get null or actual column name
  16710.                 -- Note: the output is quoted.
  16711.                 exec dbo.sp_MSget_synctran_column 
  16712.                     @ts_col = null,
  16713.                     @op_type = null , -- 'ins, 'upd', 'del'
  16714.                     @is_new = null,
  16715.                     @primary_key_bitmap = null,
  16716.                     @colname = @colname,
  16717.                     @this_col = @this_col,
  16718.                     @column = @column output,
  16719.                     @from_proc = 1,
  16720.                     @art_col = @art_col -- position in the partition.
  16721.  
  16722.                 select @cmd = @cmd + @spacer + QUOTENAME(@colname) + N' = ' + @column                 
  16723.                 select @spacer = N','
  16724.  
  16725.                 --
  16726.                 -- flush command if necessary
  16727.                 --
  16728.                 exec dbo.sp_MSflush_command @cmd output, 1, 8
  16729.             end
  16730.         end
  16731.         FETCH hCColid INTO @this_col
  16732.     end
  16733.     CLOSE hCColid
  16734.     DEALLOCATE hCColid
  16735.  
  16736.     -- save off cmd fragment
  16737.     if @num_col > 0
  16738.     begin
  16739.         --
  16740.         -- Add the where clause based on the update mode
  16741.         --
  16742.         select @colname = 'msrepl_tran_version'
  16743.         exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', @colname, 4
  16744.     end 
  16745.     else
  16746.     -- set the @@rowcount
  16747.         insert into #proctext(procedure_text) values( N' select @retcode = @retcode
  16748.     ')
  16749.  
  16750.     --
  16751.     -- continue with rest of scripting
  16752.     --
  16753.     select @cmd = N'
  16754.     select @rowcount = @@ROWCOUNT, @error = @@ERROR
  16755.     '
  16756.  
  16757.     if (@queued_pub = 1)
  16758.     begin
  16759.         select @cmd = @cmd + N'
  16760.     if (@execution_mode = @QPubWins)
  16761.         rollback tran cftpass'
  16762.     end
  16763.     insert into #proctext(procedure_text) values(@cmd)
  16764.  
  16765.     --
  16766.     -- all done
  16767.     --
  16768.     return 0
  16769. END
  16770. go
  16771.  
  16772. EXEC dbo.sp_MS_marksystemobject sp_MSscript_update_statement
  16773. GO
  16774.  
  16775. --
  16776. -- proc to generate subscriber wins resolution code block
  16777. -- for update proc used for synctran/queued
  16778. --
  16779. raiserror('Creating procedure sp_MSscript_update_subwins', 0,1)
  16780. go
  16781. create procedure sp_MSscript_update_subwins (
  16782.     @publication sysname,
  16783.     @article     sysname, 
  16784.     @objid int,
  16785.     @columns binary(32),
  16786.     @identity_insert bit)
  16787. AS
  16788. BEGIN
  16789.     declare @cmd nvarchar(4000)
  16790.             ,@artid int
  16791.             ,@pubid int
  16792.             ,@qualname nvarchar(512)
  16793.             ,@column_string nvarchar(4000)
  16794.             ,@colname      sysname
  16795.             ,@ccoltype     sysname
  16796.             ,@this_col     int
  16797.             ,@rc           int
  16798.             ,@num_col      int
  16799.             ,@art_col      int
  16800.             ,@bitstr nvarchar(20)
  16801.             ,@bytestr nvarchar(20)
  16802.             ,@isset int
  16803.             ,@timestamp_subscribed bit
  16804.  
  16805.     --
  16806.     -- initialize the vars we will use
  16807.     --
  16808.     select @pubid = pubid from syspublications where name = @publication
  16809.     select @artid = artid from sysarticles 
  16810.         where name = @article and pubid = @pubid
  16811.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  16812.  
  16813.     --
  16814.     -- special flag for timestamp column subscription
  16815.     --
  16816.     if exists (select * from sysarticles where pubid = @pubid and
  16817.         name = @article and
  16818.         status & 32 <> 0)
  16819.         select @timestamp_subscribed = 1
  16820.     else
  16821.         select @timestamp_subscribed = 0
  16822.  
  16823.     --
  16824.     -- start scripting
  16825.     --
  16826.     select @cmd = N'
  16827.     if (@error in (0, 547, 2627) and @execution_mode = @QSubWins)
  16828.     begin
  16829.         ' + N'--
  16830.         ' + N'-- Subscriber Wins resolution
  16831.         ' + N'--
  16832.         select @retcode = 0
  16833.         if (@rowcount = 0)
  16834.         begin
  16835.             --
  16836.             -- Conflict for this command
  16837.             -- Check if PK update was being done
  16838.             --'
  16839.     insert into #proctext(procedure_text) values( @cmd )
  16840.     
  16841.     --
  16842.     -- script the PK update check
  16843.     --
  16844.     select @cmd = N'
  16845.             exec @retcode = dbo.sp_MSispkupdateinconflict ' + 
  16846.         cast(@pubid as nvarchar(10)) + N', ' + cast(@artid as nvarchar(10)) + N', @bitmap'
  16847.     insert into #proctext(procedure_text) values( @cmd )
  16848.  
  16849.     select @cmd = N'
  16850.             if (@retcode = -1)
  16851.                 return -1
  16852.             if (@retcode = 0)
  16853.             begin
  16854.                 ' + N'--
  16855.                 ' + N'-- PK update is not being done
  16856.                 ' + N'-- '
  16857.     insert into #proctext(procedure_text) values( @cmd )
  16858.  
  16859.     --
  16860.     -- script the if exists code using OLD_PK
  16861.     --
  16862.     select @cmd = N'
  16863.                 if exists (select * from ' + @qualname 
  16864.     insert into #proctext(procedure_text) values( @cmd )
  16865.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  16866.     insert into #proctext(procedure_text) values( N' )')
  16867.     
  16868.     --
  16869.     -- continue scripting
  16870.     --
  16871.     select @cmd = N'
  16872.                 begin
  16873.                     ' + N'--
  16874.                     ' + N'-- row with OLD_PK exists
  16875.                     ' + N'-- update row with OLD_PK with queue values
  16876.                     ' + N'-- 
  16877.                     select @cftcase = 11
  16878.                 end'
  16879.     insert into #proctext(procedure_text) values( @cmd )
  16880.  
  16881.     select @cmd = N'
  16882.                 else
  16883.                 begin
  16884.                     ' + N'--
  16885.                     ' + N'-- row with OLD_PK does not exists
  16886.                     ' + N'-- insert row with queue values using OLD_PK
  16887.                     ' + N'-- 
  16888.                     select @cftcase = 13
  16889.                 end
  16890.             end'
  16891.     insert into #proctext(procedure_text) values( @cmd )
  16892.  
  16893.     --
  16894.     -- continue scripting
  16895.     --
  16896.     select @cmd = N'
  16897.             else
  16898.             begin
  16899.                 ' + N'--
  16900.                 ' + N'-- PK update is being done
  16901.                 ' + N'-- drop rows with OLD_PK, NEW_PK and insert row with queue values
  16902.                 ' + N'--
  16903.                 select @cftcase = 0'
  16904.     insert into #proctext(procedure_text) values( @cmd )
  16905.                 
  16906.     --
  16907.     -- script the if exists code using OLD_PK
  16908.     --
  16909.     select @cmd = N'
  16910.                 if exists (select * from ' + @qualname 
  16911.     insert into #proctext(procedure_text) values( @cmd )
  16912.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  16913.     insert into #proctext(procedure_text) values( N' )')
  16914.     
  16915.     --
  16916.     -- continue scripting
  16917.     --
  16918.     select @cmd = N'
  16919.                 begin
  16920.                     ' + N'--
  16921.                     ' + N'-- row with OLD_PK exists
  16922.                     ' + N'-- insert row with queue values using NEW_PK +
  16923.                     ' + N'-- delete row with OLD_PK
  16924.                     ' + N'-- 
  16925.                     select @cftcase = 14
  16926.                 end' 
  16927.     insert into #proctext(procedure_text) values( @cmd )
  16928.     
  16929.     --
  16930.     -- script the if exists code using NEW_PK
  16931.     --
  16932.     select @cmd = N'
  16933.                 if exists (select * from ' + @qualname 
  16934.     insert into #proctext(procedure_text) values( @cmd )
  16935.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0
  16936.     insert into #proctext(procedure_text) values( N' )')
  16937.  
  16938.     --
  16939.     -- continue scripting
  16940.     --
  16941.     select @cmd = N'
  16942.                 begin
  16943.                     ' + N'--
  16944.                     ' + N'-- row with NEW_PK exists
  16945.                     ' + N'-- case 15: rows with NEW_PK and OLD_PK exist
  16946.                     ' + N'-- update row with NEW_PK with queue values + 
  16947.                     ' + N'-- delete row with OLD_PK'
  16948.     insert into #proctext(procedure_text) values( @cmd )
  16949.  
  16950.     select @cmd = N'
  16951.                     ' + N'-- case 16: row with NEW_PK exists
  16952.                     ' + N'-- update row with NEW_PK with queue values
  16953.                     ' + N'--
  16954.                     select @cftcase = case when (@cftcase = 14) then 15 else 16 end
  16955.                 end'
  16956.     insert into #proctext(procedure_text) values( @cmd )
  16957.  
  16958.     select @cmd = N'
  16959.                 if (@cftcase = 0)
  16960.                 begin
  16961.                     ' + N'--
  16962.                     ' + N'-- no existing rows with OLD_PK or NEW_PK
  16963.                     ' + N'-- insert with queue values
  16964.                     ' + N'--
  16965.                     select @cftcase = 12
  16966.                 end
  16967.             end'
  16968.     insert into #proctext(procedure_text) values( @cmd )
  16969.  
  16970.     --
  16971.     -- continue scripting
  16972.     --
  16973.     select @cmd = N'
  16974.             ' + N'--
  16975.             ' + N'-- based on retcode do the resolution
  16976.             ' + N'-- 
  16977.             if (@cftcase in (12, 13, 14))
  16978.             begin
  16979.                 ' + N'--
  16980.                 ' + N'-- insert
  16981.                 ' + N'--'
  16982.     insert into #proctext(procedure_text) values( @cmd )
  16983.  
  16984.     --
  16985.     -- prepare the insert statement
  16986.     --
  16987.     if (@identity_insert = 1)
  16988.     begin
  16989.         -- Only to call set if identity is not marked for 'not for repl'
  16990.         -- This is to avoid security failure of 'SET' for PAL users
  16991.         if not exists (select * from syscolumns where id = @objid and
  16992.             ColumnProperty(id, name, 'IsIdNotForRepl') = 1)
  16993.         begin
  16994.             select @cmd = N'
  16995.                 set identity_insert ' + @qualname + N' on '
  16996.             insert into #proctext(procedure_text) values( @cmd )
  16997.         end
  16998.     end
  16999.  
  17000.     select @cmd = N'
  17001.                 insert into ' + @qualname + N'('
  17002.     insert into #proctext(procedure_text) values( @cmd )
  17003.  
  17004.     select @num_col = 0
  17005.             ,@art_col = 0
  17006.             ,@cmd = NULL
  17007.     create table #collisttab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  17008.     create table #worktab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  17009.     
  17010.  
  17011.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  17012.     select colid from dbo.syscolumns where id = @objid order by colid asc
  17013.  
  17014.     OPEN hCColid
  17015.     FETCH hCColid INTO @this_col
  17016.     WHILE (@@fetch_status != -1)
  17017.     begin
  17018.         -- Get the ordinal of the article partition or not.
  17019.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  17020.         if @isset = 0
  17021.         begin
  17022.             if ((@timestamp_subscribed = 1) and 
  17023.                     exists ( select * from dbo.syscolumns where id = @objid and colid = @this_col and xtype = 189))
  17024.                 select @art_col = @art_col + 1
  17025.         end
  17026.         else
  17027.             select @art_col = @art_col + 1
  17028.  
  17029.         exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output
  17030.         if @rc = 0 and EXISTS (select name from dbo.syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  17031.         begin
  17032.             if rtrim(@ccoltype) != N'timestamp' 
  17033.             begin
  17034.                 select @num_col = @num_col + 1
  17035.                         ,@bytestr = cast((1 + (@art_col-1) / 8 ) as nvarchar)
  17036.                         ,@bitstr =  cast( power(2, (@art_col-1) % 8 ) as nvarchar)
  17037.  
  17038.                 select @column_string = N'case substring(@bitmap,' + 
  17039.                     @bytestr + N',1) & ' + @bitstr + N' when ' + @bitstr + 
  17040.                     N' then @c' + cast(@this_col as nvarchar(4)) + 
  17041.                     N' else @c' + cast(@this_col as nvarchar(4)) + N'_old end '
  17042.  
  17043.                 if (@num_col = 1)
  17044.                 begin
  17045.                     select @cmd = quotename(@colname)
  17046.                     select @column_string = N'
  17047.                     ' + @column_string
  17048.                 end
  17049.                 else
  17050.                 begin
  17051.                     select @cmd = @cmd + N',' + quotename(@colname)
  17052.                     select @column_string = N'
  17053.                     , ' + @column_string
  17054.                 end
  17055.  
  17056.                 -- transfer the column list string to table if large
  17057.                 if (len(@cmd) > 3000)
  17058.                 begin
  17059.                     insert into #collisttab(procedure_text) values( @cmd )
  17060.                     select @cmd = N' '
  17061.                 end
  17062.                 insert into #worktab(procedure_text) values( @column_string )
  17063.                 
  17064.             end
  17065.         end
  17066.         FETCH hCColid INTO @this_col
  17067.     end
  17068.     CLOSE hCColid
  17069.     DEALLOCATE hCColid
  17070.  
  17071.     -- transfer the remaining column list string to table
  17072.     insert into #collisttab(procedure_text) values( @cmd )
  17073.     
  17074.     insert into #proctext(procedure_text) 
  17075.         select procedure_text from #collisttab order by c1 asc
  17076.     select @cmd = N')
  17077.                 select '
  17078.     insert into #proctext(procedure_text) values( @cmd )
  17079.     insert into #proctext(procedure_text) 
  17080.         select procedure_text from #worktab order by c1 asc
  17081.  
  17082.     if (@identity_insert = 1)
  17083.     begin
  17084.         -- Only to call set if identity is not marked for 'not for repl'
  17085.         -- This is to avoid security failure of 'SET' for PAL users
  17086.         if not exists (select * from syscolumns where id = @objid and
  17087.             ColumnProperty(id, name, 'IsIdNotForRepl') = 1)
  17088.         begin
  17089.             select @cmd = N'
  17090.                 set identity_insert ' + @qualname + N' off '
  17091.             insert into #proctext(procedure_text) values( @cmd )
  17092.         end
  17093.     end
  17094.  
  17095.     --
  17096.     -- continue with scripting
  17097.     --
  17098.     select @cmd = N'
  17099.             end
  17100.  
  17101.             if (@cftcase = 11)
  17102.             begin
  17103.                 ' + N'--
  17104.                 ' + N'-- update using OLD_PK
  17105.                 ' + N'--'
  17106.     insert into #proctext(procedure_text) values( @cmd )
  17107.  
  17108.     --
  17109.     -- prepare the column list for update statement
  17110.     --
  17111.     select @num_col = 0
  17112.             ,@art_col = 0
  17113.     create table #worktab2 ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  17114.  
  17115.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  17116.     select colid from syscolumns where id = @objid order by colid asc
  17117.  
  17118.     OPEN hCColid
  17119.     FETCH hCColid INTO @this_col
  17120.     WHILE (@@fetch_status <> -1)
  17121.     begin
  17122.         -- Get the ordinal of the article partition or not.
  17123.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  17124.         if @isset = 0
  17125.         begin
  17126.             if ((@timestamp_subscribed = 1) and 
  17127.                     exists ( select * from dbo.syscolumns where id = @objid and colid = @this_col and xtype = 189))
  17128.                 select @art_col = @art_col + 1
  17129.         end
  17130.         else
  17131.             select @art_col = @art_col + 1
  17132.  
  17133.         exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output
  17134.         if @rc = 0 and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  17135.         begin
  17136.             if (rtrim(@ccoltype) != N'timestamp') and ColumnProperty(@objid, @colname, 'IsIdentity') != 1
  17137.             begin
  17138.                 select @num_col = @num_col + 1
  17139.                         ,@bytestr = cast((1 + (@art_col-1) / 8 ) as nvarchar)
  17140.                         ,@bitstr =  cast( power(2, (@art_col-1) % 8 ) as nvarchar)
  17141.  
  17142.                 select @column_string = quotename(@colname) + N' = case substring(@bitmap,' + 
  17143.                     @bytestr + N',1) & ' + @bitstr + N' when ' + @bitstr + 
  17144.                     N' then @c' + cast(@this_col as nvarchar(4)) + 
  17145.                     N' else @c' + cast(@this_col as nvarchar(4)) + N'_old  end '
  17146.  
  17147.                 if (@num_col = 1)
  17148.                 begin
  17149.                     select @column_string = N'
  17150.                     ' + @column_string
  17151.                 end
  17152.                 else
  17153.                 begin
  17154.                     select @column_string = N'
  17155.                     , ' + @column_string
  17156.                 end
  17157.  
  17158.                 insert into #worktab2(procedure_text) values( @column_string )
  17159.                 
  17160.             end
  17161.         end
  17162.         FETCH hCColid INTO @this_col
  17163.     end
  17164.     CLOSE hCColid
  17165.     DEALLOCATE hCColid
  17166.  
  17167.     --
  17168.     -- script the update with OLD_PK statement
  17169.     --
  17170.     select @cmd = N'
  17171.                 update ' + @qualname + N' set '
  17172.     insert into #proctext(procedure_text) values( @cmd )
  17173.     insert into #proctext(procedure_text) 
  17174.         select procedure_text from #worktab2 order by c1 asc
  17175.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  17176.     
  17177.     --
  17178.     -- continue with scripting
  17179.     --
  17180.     select @cmd = N'
  17181.             end
  17182.  
  17183.             if (@cftcase in (15, 16))
  17184.             begin
  17185.                 ' + N'--
  17186.                 ' + N'-- update using NEW_PK
  17187.                 ' + N'--'
  17188.     insert into #proctext(procedure_text) values( @cmd )
  17189.                 
  17190.     --
  17191.     -- script the update with NEW_PK statement
  17192.     --
  17193.     select @cmd = N'
  17194.                 update ' + @qualname + N' set '
  17195.     insert into #proctext(procedure_text) values( @cmd )
  17196.     insert into #proctext(procedure_text) 
  17197.         select procedure_text from #worktab2 order by c1 asc
  17198.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0
  17199.     
  17200.     --
  17201.     -- continue with scripting
  17202.     --
  17203.     select @cmd = N'
  17204.             end
  17205.  
  17206.             if (@cftcase in (14, 15))
  17207.             begin
  17208.                 ' + N'--
  17209.                 ' + N'-- Do not delete if subscriber has already
  17210.                 ' + N'-- updated this row as part of this transaction
  17211.                 ' + N'--'
  17212.     insert into #proctext(procedure_text) values( @cmd )
  17213.  
  17214.     --
  17215.     -- script the if exists code using OLD_PK and msprepl_tran_version
  17216.     --
  17217.     select @cmd = N'
  17218.                 if not exists (select * from ' + @qualname 
  17219.     insert into #proctext(procedure_text) values( @cmd )
  17220.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'subwins_check', 'msrepl_tran_version', 0
  17221.     insert into #proctext(procedure_text) values( N' )')
  17222.  
  17223.     select @cmd = N'
  17224.                 begin
  17225.                     ' + N'-- 
  17226.                     ' + N'-- delete row with OLD_PK
  17227.                     ' + N'--'
  17228.     insert into #proctext(procedure_text) values( @cmd )
  17229.  
  17230.     --
  17231.     -- script delete with OLD_PK
  17232.     --
  17233.     select @cmd = N'
  17234.                     delete ' + @qualname 
  17235.     insert into #proctext(procedure_text) values( @cmd )
  17236.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  17237.  
  17238.     --
  17239.     -- continue with rest of scripting
  17240.     --
  17241.     select @cmd = N'
  17242.                 end
  17243.             end
  17244.     
  17245.             if (@@error != 0)
  17246.                 return -1
  17247.  
  17248.             select @retcode = 0
  17249.         end
  17250.     end'
  17251.     insert into #proctext(procedure_text) values( @cmd )
  17252.  
  17253.     --
  17254.     -- all done
  17255.     --
  17256.     drop table #collisttab
  17257.     drop table #worktab
  17258.     drop table #worktab2
  17259.     return 0
  17260. END
  17261. go
  17262.  
  17263. EXEC dbo.sp_MS_marksystemobject sp_MSscript_update_subwins
  17264. GO
  17265.  
  17266. --
  17267. -- proc to generate publisher wins resolution code block
  17268. -- for update proc used for synctran/queued
  17269. --
  17270. raiserror('Creating procedure sp_MSscript_update_pubwins', 0,1)
  17271. go
  17272. create procedure sp_MSscript_update_pubwins (
  17273.     @publication sysname,
  17274.     @article     sysname, 
  17275.     @objid int,
  17276.     @columns binary(32) )
  17277. AS
  17278. BEGIN
  17279.     declare @cmd nvarchar(4000)
  17280.             ,@artid int
  17281.             ,@pubid int
  17282.             ,@dest_table sysname
  17283.             ,@dest_owner nvarchar(260)
  17284.             ,@colname      sysname
  17285.             ,@ccoltype     sysname
  17286.             ,@this_col     int
  17287.             ,@rc           int
  17288.             ,@num_col      int
  17289.             ,@qualname nvarchar(512)
  17290.             ,@cast_str nvarchar(1000)
  17291.             ,@decl_str nvarchar(2000)
  17292.             ,@assign_str nvarchar(4000)
  17293.             ,@typestring nvarchar(100)
  17294.             ,@exec_str nvarchar(1000)
  17295.  
  17296.     --
  17297.     -- initialize the vars we will use
  17298.     --
  17299.     select @pubid = pubid from syspublications where name = @publication
  17300.     select @artid = artid, @dest_table = dest_table, @dest_owner = dest_owner
  17301.     from sysarticles where name = @article and pubid = @pubid
  17302.     select @dest_owner = case when (@dest_owner IS NULL) then N''
  17303.                 else quotename(@dest_owner) + N'.' end
  17304.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  17305.  
  17306.     --
  17307.     -- start scripting
  17308.     --
  17309.     select @cmd = N'
  17310.     else if (@error in (0, 547, 2627) and @execution_mode = @QPubWins)
  17311.     begin
  17312.         if (@rowcount = 1)
  17313.         begin
  17314.             ' + N'--
  17315.             ' + N'-- no conflict for this command
  17316.             ' + N'-- Check if PK update was being done
  17317.             ' + N'-- '
  17318.     insert into #proctext(procedure_text) values( @cmd )
  17319.  
  17320.     --
  17321.     -- script the PK update check
  17322.     --
  17323.     select @cmd = N'
  17324.             exec @retcode = dbo.sp_MSispkupdateinconflict ' + 
  17325.         cast(@pubid as nvarchar(10)) + N', ' + cast(@artid as nvarchar(10)) + N', @bitmap'
  17326.     insert into #proctext(procedure_text) values( @cmd )
  17327.  
  17328.     --
  17329.     -- continue scripting
  17330.     --
  17331.     select @cmd = N'
  17332.             if (@retcode = -1)
  17333.                 return -1
  17334.             if (@retcode = 0)
  17335.             begin
  17336.                 ' + N'--
  17337.                 ' + N'-- PK update is not being done
  17338.                 ' + N'-- generate delete + insert compensating action with OLD_PK
  17339.                 ' + N'-- 
  17340.                 select @cftcase = 0
  17341.             end'
  17342.     insert into #proctext(procedure_text) values( @cmd )
  17343.  
  17344.     --
  17345.     -- continue scripting
  17346.     --
  17347.     select @cmd = N'
  17348.             else
  17349.             begin
  17350.                 ' + N'--
  17351.                 ' + N'-- PK update is being done
  17352.                 ' + N'-- generate delete + insert compensating action with OLD_PK
  17353.                 ' + N'-- generate delete compensating action with NEW_PK
  17354.                 ' + N'-- 
  17355.                 select @cftcase = 1
  17356.             end
  17357.         end'
  17358.     insert into #proctext(procedure_text) values( @cmd )
  17359.  
  17360.     --
  17361.     -- continue scripting
  17362.     --
  17363.     select @cmd = N'
  17364.         else
  17365.         begin
  17366.             ' + N'--
  17367.             ' + N'-- Conflict for this command
  17368.             ' + N'-- Check if PK update was being done
  17369.             ' + N'--'
  17370.     insert into #proctext(procedure_text) values( @cmd )
  17371.  
  17372.     --
  17373.     -- script the PK update check
  17374.     --
  17375.     select @cmd = N'
  17376.             exec @retcode = dbo.sp_MSispkupdateinconflict ' + 
  17377.         cast(@pubid as nvarchar(10)) + N', ' + cast(@artid as nvarchar(10)) + N', @bitmap'
  17378.     insert into #proctext(procedure_text) values( @cmd )
  17379.  
  17380.     select @cmd = N'
  17381.             if (@retcode = -1)
  17382.                 return -1
  17383.             if (@retcode = 0)
  17384.             begin
  17385.                 ' + N'--
  17386.                 ' + N'-- PK update is not being done
  17387.                 ' + N'-- Now find the type of conflict
  17388.                 ' + N'-- '
  17389.     insert into #proctext(procedure_text) values( @cmd )
  17390.                 
  17391.     --
  17392.     -- script the if exists code using OLD_PK
  17393.     --
  17394.     select @cmd = N'
  17395.                 if exists (select * from ' + @qualname 
  17396.     insert into #proctext(procedure_text) values( @cmd )
  17397.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  17398.     insert into #proctext(procedure_text) values( N' )')
  17399.  
  17400.     --
  17401.     -- continue scripting
  17402.     --
  17403.     select @cmd = N'
  17404.                 begin
  17405.                     ' + N'--
  17406.                     ' + N'-- row exists
  17407.                     ' + N'-- generate delete + insert compensating action with OLD_PK
  17408.                     ' + N'--
  17409.                     select @cftcase = 11
  17410.                 end'
  17411.     insert into #proctext(procedure_text) values( @cmd )
  17412.     select @cmd = N'
  17413.                 else
  17414.                 begin
  17415.                     ' + N'--
  17416.                     ' + N'-- row does not exist
  17417.                     ' + N'-- generate delete compensating action with OLD_PK
  17418.                     ' + N'--
  17419.                     select @cftcase = 13
  17420.                 end
  17421.             end'
  17422.     insert into #proctext(procedure_text) values( @cmd )
  17423.             
  17424.     --
  17425.     -- continue scripting
  17426.     --
  17427.     select @cmd = N'
  17428.             else
  17429.             begin
  17430.                 ' + N'--
  17431.                 ' + N'-- PK update is being done
  17432.                 ' + N'-- Now find the type of conflict
  17433.                 ' + N'-- 
  17434.                 select @cftcase = 0'
  17435.     insert into #proctext(procedure_text) values( @cmd )
  17436.                 
  17437.     --
  17438.     -- script the if exists code using OLD_PK
  17439.     --
  17440.     select @cmd = N'
  17441.                 if exists (select * from ' + @qualname 
  17442.     insert into #proctext(procedure_text) values( @cmd )
  17443.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  17444.     insert into #proctext(procedure_text) values( N' )')
  17445.  
  17446.     --
  17447.     -- continue scripting
  17448.     --
  17449.     select @cmd = N'
  17450.                 begin
  17451.                     ' + N'--
  17452.                     ' + N'-- row with OLD_PK exists
  17453.                     ' + N'-- generate delete compensating action with OLD_PK +
  17454.                     ' + N'-- insert compensating action with OLD_PK 
  17455.                     ' + N'--
  17456.                     select @cftcase = 14
  17457.                 end'
  17458.     insert into #proctext(procedure_text) values( @cmd )
  17459.  
  17460.     --
  17461.     -- script the if exists code using NEW_PK
  17462.     --
  17463.     select @cmd = N'
  17464.                 if exists (select * from ' + @qualname 
  17465.     insert into #proctext(procedure_text) values( @cmd )
  17466.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0
  17467.     insert into #proctext(procedure_text) values( N' )')
  17468.  
  17469.     --
  17470.     -- continue scripting
  17471.     --
  17472.     select @cmd = N'
  17473.                 begin
  17474.                     ' + N'--
  17475.                     ' + N'-- row with NEW_PK exists
  17476.                     ' + N'-- case 15: rows with NEW_PK and OLD_PK exist
  17477.                     ' + N'-- generate delete compensating actions with OLD_PK, NEW_PK +
  17478.                     ' + N'-- insert compensating actions with OLD_PK, NEW_PK' 
  17479.     insert into #proctext(procedure_text) values( @cmd )
  17480.     select @cmd = N'
  17481.                     ' + N'-- case 16: row with NEW_PK exists and OLD_PK does not exist
  17482.                     ' + N'-- generate delete compensating action with OLD_PK, NEW_PK +
  17483.                     ' + N'-- insert compensating action with NEW_PK 
  17484.                     ' + N'--
  17485.                     select @cftcase = case when (@cftcase = 14) then 15 else 16 end
  17486.                 end'
  17487.     insert into #proctext(procedure_text) values( @cmd )
  17488.  
  17489.     --
  17490.     -- continue scripting
  17491.     --    
  17492.     select @cmd = N'
  17493.                 else
  17494.                 begin
  17495.                     ' + N'--
  17496.                     ' + N'-- row with NEW_PK does not exists
  17497.                     ' + N'-- case 12 : no existing rows with OLD_PK or NEW_PK
  17498.                     ' + N'-- generate delete compensating action with OLD_PK, NEW_PK '
  17499.     insert into #proctext(procedure_text) values( @cmd )
  17500.     select @cmd = N'
  17501.                     ' + N'-- case 17 : row with OLD_PK exist and NEW_PK does not exist 
  17502.                     ' + N'-- generate delete compensating action with OLD_PK, NEW_PK +
  17503.                     ' + N'-- insert compensating action with OLD_PK 
  17504.                     ' + N'-- 
  17505.                     select @cftcase = case when (@cftcase = 0) then 12 else 17 end 
  17506.                 end '
  17507.     insert into #proctext(procedure_text) values( @cmd )
  17508.     select @cmd = N'
  17509.             end
  17510.         end'         
  17511.     insert into #proctext(procedure_text) values( @cmd )
  17512.  
  17513.     --
  17514.     -- continue scripting
  17515.     --
  17516.     select @cmd = N'
  17517.         if (@cftcase in (0, 1, 11, 12, 13, 14, 15, 16, 17))
  17518.         begin
  17519.             ' + N'--
  17520.             ' + N'-- generation of delete compensating command with OLD_PK
  17521.             ' + N'--'
  17522.     insert into #proctext(procedure_text) values( @cmd )
  17523.  
  17524.     --
  17525.     -- generate delete compensating cmd with OLD_PK
  17526.     --
  17527.     select @cmd = N'
  17528.             select @cmd = ''DELETE ' + master.dbo.fn_MSgensqescstr(@dest_owner) collate database_default 
  17529.         + quotename(master.dbo.fn_MSgensqescstr(@dest_table) collate database_default) + N' '' + '
  17530.     insert into #proctext(procedure_text) values( @cmd )
  17531.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'qcft_comp', NULL, 0, 'del'
  17532.     
  17533.     --
  17534.     -- script the sending command
  17535.     --
  17536.     exec sp_MSscript_compensating_send @pubid, @artid, 0, 1
  17537.     
  17538.     --
  17539.     -- continue scripting
  17540.     --
  17541.     select @cmd = N'
  17542.         end
  17543.         
  17544.         if (@cftcase in (1, 12, 15, 16, 17))
  17545.         begin
  17546.             ' + N'--
  17547.             ' + N'-- generation of delete compensating command with NEW_PK
  17548.             ' + N'--'
  17549.     insert into #proctext(procedure_text) values( @cmd )
  17550.  
  17551.     --
  17552.     -- generate delete compensating cmd with NEW_PK
  17553.     --
  17554.     select @cmd = N'
  17555.             select @cmd = ''DELETE ' + master.dbo.fn_MSgensqescstr(@dest_owner) collate database_default 
  17556.         + quotename(master.dbo.fn_MSgensqescstr(@dest_table) collate database_default) + N' '' + '
  17557.     insert into #proctext(procedure_text) values( @cmd )
  17558.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'qcft_comp', NULL, 0, 'ins'
  17559.     
  17560.     --
  17561.     -- script the sending command
  17562.     --
  17563.     exec sp_MSscript_compensating_send @pubid, @artid, 0, 1
  17564.     
  17565.     --
  17566.     -- continue scripting
  17567.     --
  17568.     select @cmd = N'
  17569.         end
  17570.  
  17571.         if (@cftcase in (0, 1, 11, 14, 15, 17))
  17572.         begin
  17573.             ' + N'--
  17574.             ' + N'-- generate and send insert compensating command with OLD_PK
  17575.             ' + N'--'
  17576.     insert into #proctext(procedure_text) values( @cmd )
  17577.  
  17578.     --
  17579.     -- script compensating insert with OLD_PK
  17580.     --
  17581.     exec dbo.sp_MSscript_compensating_insert @publication, @article, @objid, @columns, 1
  17582.     
  17583.     --
  17584.     -- continue scripting
  17585.     --
  17586.     select @cmd = N'
  17587.         end
  17588.  
  17589.         if (@cftcase in (15, 16))
  17590.         begin
  17591.             ' + N'--
  17592.             ' + N'-- generate and send insert compensating command with NEW_PK
  17593.             ' + N'--'
  17594.     insert into #proctext(procedure_text) values( @cmd )
  17595.  
  17596.     --
  17597.     -- script compensating insert with NEW_PK
  17598.     --
  17599.     exec dbo.sp_MSscript_compensating_insert @publication, @article, @objid, @columns, 0
  17600.     
  17601.     --
  17602.     -- continue with scripting
  17603.     --
  17604.     select @cmd = N'
  17605.         end
  17606.         select @retcode = 0
  17607.     end'
  17608.     insert into #proctext(procedure_text) values( @cmd )
  17609.     
  17610.     --
  17611.     -- all done
  17612.     --
  17613.     return 0    
  17614. END
  17615. go
  17616.  
  17617. EXEC dbo.sp_MS_marksystemobject sp_MSscript_update_pubwins
  17618. GO
  17619.  
  17620. raiserror('Creating procedure sp_MSscript_delete_statement', 0,1)
  17621. go
  17622. create procedure sp_MSscript_delete_statement (
  17623.     @publication sysname,
  17624.     @article     sysname, 
  17625.     @objid int,
  17626.     @columns binary(32),
  17627.     @queued_pub bit = 0
  17628. )
  17629. as
  17630. BEGIN
  17631.     declare @cmd          nvarchar(4000)
  17632.     declare @qualname     nvarchar(512)
  17633.  
  17634.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  17635.  
  17636.     --
  17637.     -- start scripting
  17638.     --
  17639.     select @cmd = N'
  17640.     ' + N'--
  17641.     ' + N'-- detection/conflict resolution stage
  17642.     ' + N'--'
  17643.     
  17644.     if (@queued_pub = 1)
  17645.     begin
  17646.         select @cmd = @cmd + N'
  17647.     if (@execution_mode = @QPubWins)
  17648.         save tran cftpass
  17649.     '
  17650.     end
  17651.     insert into #proctext(procedure_text) values( @cmd )
  17652.  
  17653.     --
  17654.     -- delete statement
  17655.     --
  17656.     select @cmd = N'
  17657.     delete ' + @qualname 
  17658.     insert into #proctext(procedure_text) values( @cmd )
  17659.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', 'msrepl_tran_version', 4
  17660.  
  17661.     --
  17662.     -- continue with scripting
  17663.     --
  17664.     select @cmd = N'
  17665.     select @rowcount = @@ROWCOUNT, @error = @@ERROR
  17666.     '
  17667.  
  17668.     if (@queued_pub = 1)
  17669.     begin
  17670.         select @cmd = @cmd + N'
  17671.     if (@execution_mode = @QPubWins)
  17672.         rollback tran cftpass
  17673.     '
  17674.     end
  17675.     insert into #proctext(procedure_text) values( @cmd )
  17676.  
  17677.     --
  17678.     -- all done
  17679.     --
  17680.     return 0
  17681. END
  17682. go
  17683.  
  17684. EXEC dbo.sp_MS_marksystemobject sp_MSscript_delete_statement
  17685. GO
  17686.  
  17687. --
  17688. -- proc to generate subscriber wins resolution code block
  17689. -- for delete proc used for synctran/queued
  17690. --
  17691. raiserror('Creating procedure sp_MSscript_delete_subwins', 0,1)
  17692. go
  17693. create procedure sp_MSscript_delete_subwins (
  17694.     @publication sysname,
  17695.     @article     sysname, 
  17696.     @objid int,
  17697.     @columns binary(32) )
  17698. AS
  17699. BEGIN
  17700.     declare @cmd nvarchar(4000)
  17701.             ,@qualname nvarchar(512)
  17702.  
  17703.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  17704.  
  17705.     --
  17706.     -- start scripting
  17707.     --
  17708.     select @cmd = N'
  17709.     if (@error in (0, 547) and @execution_mode = @QSubWins)
  17710.     begin
  17711.         ' + N'--
  17712.         ' + N'-- Subscriber Wins resolution
  17713.         ' + N'--
  17714.         select @retcode = 0
  17715.         if (@rowcount = 0)
  17716.         begin
  17717.             --
  17718.             -- Conflict for this command
  17719.             -- Delete using PK only
  17720.             --'
  17721.     insert into #proctext(procedure_text) values( @cmd )
  17722.  
  17723.     --
  17724.     -- generate the delete statement
  17725.     --
  17726.     select @cmd = N'
  17727.             delete ' + @qualname 
  17728.     insert into #proctext(procedure_text) values( @cmd )
  17729.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  17730.  
  17731.     --
  17732.     -- continue with scripting
  17733.     --
  17734.     select @cmd = N'            
  17735.             if (@@error != 0 or @retcode != 0)
  17736.                 return -1
  17737.         end
  17738.     end'
  17739.     insert into #proctext(procedure_text) values( @cmd )
  17740.  
  17741.     --
  17742.     -- all done
  17743.     --
  17744.     return 0
  17745. END
  17746. go
  17747.  
  17748. EXEC dbo.sp_MS_marksystemobject sp_MSscript_delete_subwins
  17749. GO
  17750.  
  17751. --
  17752. -- proc that generates a compensating insert command string
  17753. -- specify the type of proc where this generation will be used
  17754. --
  17755. raiserror('Creating procedure sp_MSscript_compensating_insert', 0,1)
  17756. go
  17757. create procedure sp_MSscript_compensating_insert (
  17758.     @publication sysname,
  17759.     @article     sysname, 
  17760.     @objid int,
  17761.     @columns binary(32),
  17762.     @proctype    int = 1)        -- 0 = use new_pk, 1 = use old_pk
  17763. AS
  17764. BEGIN
  17765.     declare @cmd nvarchar(4000)
  17766.             ,@artid int
  17767.             ,@pubid int
  17768.             ,@dest_table sysname
  17769.             ,@dest_owner nvarchar(260)
  17770.             ,@colname      sysname
  17771.             ,@ccoltype     sysname
  17772.             ,@this_col     int
  17773.             ,@rc           int
  17774.             ,@num_col      int
  17775.             ,@qualname nvarchar(540)
  17776.             ,@cast_str nvarchar(4000)
  17777.             ,@column_string nvarchar(4000)
  17778.             ,@ins_cmd nvarchar(255)
  17779.             ,@startoffset int
  17780.             ,@setprefix bit
  17781.             ,@commandlen int
  17782.             ,@fragmentlen int
  17783.             ,@collen int
  17784.             ,@first_time bit
  17785.             ,@fullcastlen int
  17786.             ,@splitlen int
  17787.  
  17788.     --
  17789.     -- initialize the vars we will use
  17790.     --
  17791.     select @pubid = pubid from syspublications where name = @publication
  17792.     select @artid = artid, @dest_table = dest_table, 
  17793.         @dest_owner = dest_owner, @ins_cmd = ins_cmd from sysarticles 
  17794.     where name = @article and pubid = @pubid
  17795.     select @dest_owner = case when (@dest_owner IS NULL) then N''
  17796.                 else quotename(@dest_owner) + N'.' end
  17797.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  17798.  
  17799.     --
  17800.     -- The compensating command will be split into one or more
  17801.     -- fragment commands if the length exceeds 3450 characters in length 
  17802.     -- (to accomodate compensating server/db names)
  17803.     -- For correctly estimating the length of the compensating command
  17804.     -- we have to take the max column length of the data into consideration along
  17805.     -- with the scripting command length
  17806.     --
  17807.  
  17808.     --
  17809.     -- use the insert command if available
  17810.     --
  17811.     select @commandlen = 0
  17812.             ,@setprefix = 1
  17813.  
  17814.     if (@ins_cmd = N'SQL')
  17815.     begin
  17816.         select @cmd = N'
  17817.             select @cmd = ''INSERT INTO ' + master.dbo.fn_MSgensqescstr(@dest_owner) collate database_default 
  17818.                         + quotename(master.dbo.fn_MSgensqescstr(@dest_table) collate database_default) + N''' + 
  17819.                         '' SELECT '' + '
  17820.     end
  17821.     else
  17822.     begin
  17823.         select @cmd = N'
  17824.             select @cmd = ''EXEC ' + substring(@ins_cmd, 5, len(@ins_cmd) - 4) + N' '' + '
  17825.     end
  17826.     insert into #proctext(procedure_text) values( @cmd )
  17827.      select @commandlen = @commandlen + len(@cmd)
  17828.     
  17829.     select @num_col = 0
  17830.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  17831.     select colid, length from syscolumns where id = @objid order by colid asc
  17832.  
  17833.     OPEN hCColid
  17834.     FETCH hCColid INTO @this_col, @collen
  17835.     WHILE (@@fetch_status != -1)
  17836.     begin
  17837.         exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 1, @colname output, @ccoltype output
  17838.         if @rc = 0  and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  17839.         begin
  17840.             if rtrim(@ccoltype) not like N'timestamp' 
  17841.             begin
  17842.                 select @num_col = @num_col + 1
  17843.  
  17844.                 --
  17845.                 -- Compute the command fragment length needed for this column
  17846.                 -- based on the coltype
  17847.                 --                
  17848.                 if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('ntext','text','image'))
  17849.                 begin
  17850.                     --
  17851.                     -- For compensating commands we have to include the text and image data
  17852.                     -- as the custom procs used by Distribution process expects them - as it
  17853.                     -- done for regular transactional replication - but we will only send NULLs
  17854.                     -- as it is not possible to ascertain the size of the data during the generation
  17855.                     --        
  17856.                     select @cast_str = N' ''null'' '
  17857.                     select @fullcastlen = len(@cast_str)
  17858.                     select @fragmentlen = @fullcastlen + 4 + @collen
  17859.                 end
  17860.                 else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('varchar','nvarchar','char','nchar'))
  17861.                 begin
  17862.                     if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('nvarchar', 'nchar'))
  17863.                         select @collen = (@collen / 2)
  17864.     
  17865.                     select @cast_str = case 
  17866.                             when (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('nvarchar', 'nchar'))
  17867.                                 then N' ISNULL(''N'''''' + master.dbo.fn_MSgensqescstr(' + quotename(@colname) + N') collate database_default + '''''''', ''null'') '
  17868.                                 else N' ISNULL('''''''' + master.dbo.fn_MSgensqescstr(' + quotename(@colname) + N') collate database_default + '''''''', ''null'') '
  17869.                             end
  17870.        
  17871.                     select @fullcastlen = len(@cast_str)
  17872.                     select @fragmentlen = @fullcastlen + 4 + @collen
  17873.                 end
  17874.                 else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('binary','varbinary'))
  17875.                 begin
  17876.                     --
  17877.                     -- each byte has 2 nibbles - we need a char to represent each nibble
  17878.                     --
  17879.                     select @collen = @collen * 2
  17880.                     select @cast_str = N' ISNULL(master.dbo.fn_varbintohexsubstring(1,' + quotename(@colname) + N',1,0) collate database_default, ''null'') '
  17881.                     select @fullcastlen = len(@cast_str)
  17882.                     select @fragmentlen = @fullcastlen + 4 + @collen + 2
  17883.                 end
  17884.                 else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('bit','bigint','int','smallint','tinyint','float','real','decimal','numeric'))
  17885.                 begin
  17886.                     select @collen = 40
  17887.                     select @cast_str = N' ISNULL(CAST(' + quotename(@colname) + N' as nvarchar), ''null'') '
  17888.                     select @fragmentlen = len(@cast_str) + @collen
  17889.                 end
  17890.                 else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('money','smallmoney'))
  17891.                 begin
  17892.                     select @collen = 40
  17893.                     select @cast_str = N' ISNULL(CONVERT(nvarchar(40),' + quotename(@colname) + N',2), ''null'') '
  17894.                     select @fragmentlen = len(@cast_str) + @collen
  17895.                 end
  17896.                 else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'uniqueidentifier')
  17897.                 begin
  17898.                     select @collen = 40
  17899.                     select @cast_str = N' ISNULL('''''''' + CAST(' + quotename(@colname) + N' as nvarchar(40)) + '''''''', ''null'') '
  17900.                     select @fragmentlen = len(@cast_str) + @collen
  17901.                 end
  17902.                 else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('datetime','smalldatetime'))
  17903.                 begin
  17904.                     select @collen = 40
  17905.                     select @cast_str = N' ISNULL('''''''' + CONVERT(nvarchar(40), ' + quotename(@colname) + N', 112) + N'' '' +  CONVERT(nvarchar(40), ' + quotename(@colname) + N', 114) + '''''''', ''null'') '
  17906.                     select @fragmentlen = len(@cast_str) + @collen
  17907.                 end
  17908.                 else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'sql_variant')
  17909.                 begin
  17910.                     --
  17911.                     -- need to revisit this later
  17912.                     --
  17913.                     select @cast_str = N' ISNULL(master.dbo.fn_sqlvarbasetostr(' + quotename(@colname) + N' ) collate database_default, ''null'') '
  17914.                     select @fragmentlen = len(@cast_str) + @collen
  17915.                 end                    
  17916.                 else
  17917.                 begin
  17918.                     select @collen = 40
  17919.                     select @cast_str = N' ISNULL(CAST(' + quotename(@colname) + N' as nvarchar), ''null'') '
  17920.                     select @fragmentlen = len(@cast_str) + @collen
  17921.                 end
  17922.             
  17923.                 --
  17924.                 -- for fixed datatypes - we will not split the data at all we will
  17925.                 -- flush the command script and continue
  17926.                 -- for varying/large datatypes, we will have to split data if necessary
  17927.                 --
  17928.                 if ((lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('varchar','nvarchar','char','nchar','binary','varbinary')) 
  17929.                         and (@fragmentlen + @commandlen > 3450))
  17930.                 begin
  17931.                      --
  17932.                      -- the column length is too big, we have to break the data string
  17933.                      -- initialize
  17934.                      --
  17935.                     if (@num_col = 1)
  17936.                     begin
  17937.                         select @column_string = N'
  17938.                 ' 
  17939.                     end
  17940.                     else
  17941.                     begin
  17942.                         select @column_string = N'
  17943.                 + '','' + ' 
  17944.                     end
  17945.  
  17946.                     --
  17947.                     -- use substring to break the string value in the
  17948.                     -- compensating command
  17949.                     --
  17950.                     select @first_time = 1
  17951.                             ,@startoffset = 1
  17952.                     while (@collen > 0)
  17953.                     begin
  17954.                          select @splitlen = case when ((@first_time = 1) or (@collen > 3450))
  17955.                                                  then (3450 - @commandlen - 30 - @fullcastlen)
  17956.                                                  else @collen end
  17957.                          if (@splitlen < 1)
  17958.                          begin
  17959.                              --
  17960.                              -- we have overcompensated the splitlen
  17961.                              -- set to half of the column length
  17962.                              --
  17963.                              select @splitlen = @collen / 2
  17964.                          end
  17965.  
  17966.                         --
  17967.                         -- Do we need to put quotes (many datatypes need it)
  17968.                         --
  17969.                          if (@first_time = 1)
  17970.                          begin
  17971.                             if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('varchar','nvarchar','char','nchar'))
  17972.                                 select @column_string = case 
  17973.                                     when (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('nvarchar', 'nchar'))
  17974.                                         then @column_string + N' ISNULL(''N'''''' + master.dbo.fn_MSgensqescstr( '
  17975.                                         else @column_string + N' ISNULL('''''''' + master.dbo.fn_MSgensqescstr( '
  17976.                                     end
  17977.                             else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('binary','varbinary'))
  17978.                                 select @column_string = @column_string + N' ISNULL(master.dbo.fn_varbintohexsubstring(1,' 
  17979.                         end
  17980.                          else
  17981.                          begin
  17982.                             if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('varchar','nvarchar','char','nchar'))
  17983.                                  select @column_string = N' + ISNULL(master.dbo.fn_MSgensqescstr( '
  17984.                             else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('binary','varbinary'))
  17985.                                 select @column_string = @column_string + N' + ISNULL(master.dbo.fn_varbintohexsubstring(0,' 
  17986.                          end
  17987.  
  17988.                         --
  17989.                         -- prepare the substring script
  17990.                         --
  17991.                         if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('varchar','nvarchar','char','nchar'))
  17992.                             select @cast_str = N'SUBSTRING(' + quotename(@colname) + N', ' + cast(@startoffset as nvarchar) + N', ' +  cast(@splitlen as nvarchar) + N')'
  17993.                         else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('binary','varbinary'))
  17994.                             select @cast_str = quotename(@colname) + N', ' + cast(@startoffset as nvarchar) + N', ' +  cast((@splitlen/2) as nvarchar)
  17995.  
  17996.                         if (@first_time = 1)
  17997.                          begin
  17998.                             select @cast_str = @cast_str + N') collate database_default, ''null'') '
  17999.                                     ,@first_time = 0
  18000.                          end
  18001.                          else
  18002.                          begin
  18003.                             if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('varchar','nvarchar','char','nchar'))
  18004.                             begin
  18005.                                 --
  18006.                                 -- for strings the last fragment needs the single
  18007.                                 -- quote to be added for the string
  18008.                                 --
  18009.                                 select @cast_str = @cast_str + N') collate database_default '
  18010.                                 select @cast_str = case 
  18011.                                     when (@collen - @splitlen < 1)
  18012.                                         then @cast_str + N'+ '''''''', '''') '                                            
  18013.                                         else @cast_str + N', '''') ' 
  18014.                                     end
  18015.                             end
  18016.                             else if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('binary','varbinary'))
  18017.                                 select @cast_str = @cast_str + N') collate database_default, '''') '
  18018.                         end
  18019.                                  
  18020.                         select @column_string = @column_string + @cast_str
  18021.                         insert into #proctext(procedure_text) values( @column_string )
  18022.  
  18023.                         if (@fragmentlen + @commandlen > 3450)
  18024.                         begin
  18025.                             select @cmd = N'
  18026.             from ' + @qualname 
  18027.                             insert into #proctext(procedure_text) values( @cmd )
  18028.                             if (@proctype = 1)
  18029.                                 exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0, 'del'
  18030.                             else
  18031.                                 exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0, 'ins'
  18032.                             exec sp_MSscript_compensating_send @pubid, @artid, 1, @setprefix
  18033.                             if (@setprefix = 1)
  18034.                                 select @setprefix = 0
  18035.  
  18036.                             select @cmd = N'
  18037.             select @cmd = N''''' 
  18038.                             insert into #proctext(procedure_text) values( @cmd )
  18039.                             select @commandlen = 0
  18040.                         end
  18041.                         else
  18042.                             select @commandlen = @commandlen + len(@column_string)
  18043.  
  18044.                         --
  18045.                         -- update vars for next round
  18046.                         --
  18047.                         select @collen = @collen - @splitlen
  18048.                                 ,@column_string = N''
  18049.                                 ,@startoffset = case 
  18050.                                     when (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) in ('binary','varbinary')) 
  18051.                                         then (@splitlen/2) + @startoffset 
  18052.                                         else @splitlen + @startoffset 
  18053.                                     end
  18054.                         select @fragmentlen = @fullcastlen + 4 + @collen
  18055.                     end                            
  18056.  
  18057.                     --
  18058.                     -- we done with this column now
  18059.                     -- skip processing further and continue
  18060.                     --                        
  18061.                     select @commandlen = @commandlen + len(@column_string)
  18062.                  end
  18063.                  else
  18064.                  begin
  18065.                     --
  18066.                     -- Handling general fixed type column cases
  18067.                     --
  18068.                     if (@num_col = 1)
  18069.                     begin
  18070.                         select @column_string = N'
  18071.                 ' + @cast_str
  18072.                     end
  18073.                     else
  18074.                     begin
  18075.                         select @column_string = N'
  18076.                 + '','' + ' + @cast_str
  18077.                     end
  18078.  
  18079.                     --
  18080.                     -- check if we need to flush the command first
  18081.                     --
  18082.                     if (@fragmentlen + len(@column_string) + @commandlen > 3450)
  18083.                     begin
  18084.                         --
  18085.                         -- send this compensating command first
  18086.                         --
  18087.                         select @cmd = N'
  18088.             from ' + @qualname 
  18089.                         insert into #proctext(procedure_text) values( @cmd )
  18090.  
  18091.                         if (@proctype = 1)
  18092.                             exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0, 'del'
  18093.                         else
  18094.                             exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0, 'ins'
  18095.         
  18096.                         exec sp_MSscript_compensating_send @pubid, @artid, 1, @setprefix
  18097.                         if (@setprefix = 1)
  18098.                             select @setprefix = 0
  18099.  
  18100.                         select @cmd = N'
  18101.             select @cmd = N'' ''' 
  18102.                         insert into #proctext(procedure_text) values( @cmd )
  18103.                         select @commandlen = 0                    
  18104.                     end
  18105.  
  18106.                     --
  18107.                     -- script out the column string
  18108.                     --
  18109.                     insert into #proctext(procedure_text) values( @column_string )
  18110.  
  18111.                     --
  18112.                     -- if we are processing sql_variants, flush the command again
  18113.                     --
  18114.                     if (lower(@ccoltype collate SQL_Latin1_General_CP1_CS_AS) = 'sql_variant')
  18115.                     begin
  18116.                         --
  18117.                         -- send this compensating command first
  18118.                         --
  18119.                         select @cmd = N'
  18120.             from ' + @qualname 
  18121.                         insert into #proctext(procedure_text) values( @cmd )
  18122.  
  18123.                         if (@proctype = 1)
  18124.                             exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0, 'del'
  18125.                         else
  18126.                             exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0, 'ins'
  18127.         
  18128.                         exec sp_MSscript_compensating_send @pubid, @artid, 1, @setprefix
  18129.                         if (@setprefix = 1)
  18130.                             select @setprefix = 0
  18131.  
  18132.                         select @cmd = N'
  18133.             select @cmd = N'' ''' 
  18134.                         insert into #proctext(procedure_text) values( @cmd )
  18135.                         select @commandlen = 0                    
  18136.                     end
  18137.                     else
  18138.                         select @commandlen = @commandlen + @fragmentlen + len(@column_string)
  18139.                 end
  18140.             end
  18141.         end
  18142.  
  18143.         --
  18144.         -- process the next column
  18145.         --
  18146.         FETCH hCColid INTO @this_col, @collen
  18147.     end
  18148.     CLOSE hCColid
  18149.     DEALLOCATE hCColid
  18150.  
  18151.     --
  18152.     -- Check if we need to flush the command one more time (final)
  18153.     --
  18154.     if (@commandlen > 0)
  18155.     begin
  18156.         --
  18157.         -- send the last fragment of the command
  18158.         --
  18159.         select @cmd = N'
  18160.             from ' + @qualname 
  18161.         insert into #proctext(procedure_text) values( @cmd )
  18162.  
  18163.         if (@proctype = 1)
  18164.             exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0, 'del'
  18165.         else
  18166.             exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0, 'ins'
  18167.         exec sp_MSscript_compensating_send @pubid, @artid, 0, @setprefix
  18168.     end
  18169.  
  18170.     --
  18171.     -- all done
  18172.     --
  18173.     return 0
  18174. END
  18175. go
  18176.  
  18177. EXEC dbo.sp_MS_marksystemobject sp_MSscript_compensating_insert
  18178. GO
  18179.  
  18180. --
  18181. -- proc to generate publisher wins resolution code block
  18182. -- for delete proc used for synctran/queued
  18183. --
  18184. raiserror('Creating procedure sp_MSscript_delete_pubwins', 0,1)
  18185. go
  18186. create procedure sp_MSscript_delete_pubwins (
  18187.     @publication sysname,
  18188.     @article     sysname, 
  18189.     @objid int,
  18190.     @columns binary(32) )
  18191. AS
  18192. BEGIN
  18193.     declare @cmd nvarchar(4000)
  18194.             ,@artid int
  18195.             ,@pubid int
  18196.             ,@dest_table sysname
  18197.             ,@qualname nvarchar(512)
  18198.  
  18199.     --
  18200.     -- initialize the vars we will use
  18201.     --
  18202.     select @pubid = pubid from syspublications where name = @publication
  18203.     select @artid = artid, @dest_table = dest_table from sysarticles 
  18204.         where name = @article and pubid = @pubid
  18205.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  18206.  
  18207.     --
  18208.     -- start scripting
  18209.     --
  18210.     select @cmd = N'
  18211.     else if (@error in (0, 547) and @execution_mode = @QPubWins)
  18212.     begin
  18213.         ' + N'--
  18214.         ' + N'-- Publisher Wins resolution
  18215.         ' + N'-- Find where we have to generate compensating action
  18216.         ' + N'--
  18217.         if (@rowcount = 1)
  18218.         begin
  18219.             ' + N'--
  18220.             ' + N'-- no conflict for this command
  18221.             ' + N'-- generate insert compensating action
  18222.             ' + N'--            
  18223.             select @cftcase = 0
  18224.         end
  18225.         else
  18226.         begin
  18227.             ' + N'--
  18228.             ' + N'-- conflict for this command
  18229.             ' + N'--'
  18230.     insert into #proctext(procedure_text) values( @cmd )
  18231.             
  18232.     --
  18233.     -- script the if exists code
  18234.     --
  18235.     select @cmd = N'
  18236.             if exists (select * from ' + @qualname 
  18237.     insert into #proctext(procedure_text) values( @cmd )
  18238.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  18239.     insert into #proctext(procedure_text) values( N'            )')
  18240.  
  18241.     --
  18242.     -- continue with scripting
  18243.     --
  18244.     select @cmd = N'
  18245.             begin
  18246.                 ' + N'--
  18247.                 ' + N'-- row exists
  18248.                 ' + N'-- generate insert compensating action
  18249.                 ' + N'--
  18250.                 select @cftcase = 31
  18251.             end
  18252.             else
  18253.             begin
  18254.                 ' + N'--
  18255.                 ' + N'-- row does not exist
  18256.                 ' + N'-- do nothing
  18257.                 ' + N'--
  18258.                 select @cftcase = 33
  18259.             end
  18260.         end'
  18261.     insert into #proctext(procedure_text) values( @cmd )
  18262.         
  18263.     select @cmd = N'
  18264.         if (@cftcase in (0, 31))
  18265.         begin
  18266.             ' + N'--
  18267.             ' + N'-- generation and sending of compensating command
  18268.             ' + N'--'
  18269.     insert into #proctext(procedure_text) values( @cmd )
  18270.  
  18271.     --
  18272.     -- generate the compensating update command
  18273.     --
  18274.     exec dbo.sp_MSscript_compensating_insert @publication, @article, @objid, @columns, 1
  18275.  
  18276.     --
  18277.     -- continue with scripting
  18278.     --
  18279.     select @cmd = N'
  18280.         end
  18281.         select @retcode = 0
  18282.     end'
  18283.     insert into #proctext(procedure_text) values( @cmd )
  18284.  
  18285.     --
  18286.     -- all done
  18287.     --
  18288.     return 0    
  18289. END
  18290. go
  18291.  
  18292. EXEC dbo.sp_MS_marksystemobject sp_MSscript_delete_pubwins
  18293. GO
  18294.  
  18295. raiserror('Creating procedure sp_MSscript_beginproc', 0,1)
  18296. go
  18297. create procedure sp_MSscript_beginproc (
  18298.     @publication  sysname, 
  18299.     @article      sysname, 
  18300.     @procname     sysname,
  18301.     @source_objid int        output,
  18302.     @columns      binary(32) output)
  18303. as
  18304. BEGIN
  18305.     declare @cmd nvarchar(4000)
  18306.     declare @source_table sysname
  18307.     declare @owner sysname
  18308.  
  18309.     -- Retrieve underlying table name and replicated columns
  18310.     select @source_table = object_name(objid), @source_objid = objid, @columns = columns from sysarticles a, syspublications p
  18311.         where a.name = @article and
  18312.               p.name = @publication and
  18313.               a.pubid = p.pubid
  18314.  
  18315.     -- Get the object owner name
  18316.     select @owner = u.name from sysusers u, sysobjects o where 
  18317.         o.id = @source_objid and
  18318.         o.uid = u.uid
  18319.             
  18320.     if @source_table IS NULL
  18321.     begin
  18322.         raiserror (20506, 16, 1,  @source_table, 'sp_MSscript_beginproc')
  18323.         return 0
  18324.     end
  18325.  
  18326.     -- Construct proc name
  18327.     -- Create proc under the table owner account to preserve the ownership chain
  18328.     select @cmd = N'create procedure '+QUOTENAME(@owner)+ N'.'+ QUOTENAME(@procname) + N' (
  18329.     @orig_server sysname, @orig_db sysname,'
  18330.     exec dbo.sp_MSflush_command @cmd output, 1
  18331.  
  18332.     return 1
  18333. END
  18334. go
  18335.  
  18336. EXEC dbo.sp_MS_marksystemobject sp_MSscript_beginproc
  18337. GO
  18338.  
  18339. raiserror('Creating procedure sp_MSscript_security', 0,1)
  18340. go
  18341. create procedure sp_MSscript_security (
  18342.     @publication sysname)
  18343. as
  18344. BEGIN
  18345.     declare @cmd nvarchar(4000)
  18346.     
  18347.     select @cmd = N'
  18348.     ' + N'--
  18349.     ' + N'-- Check for security
  18350.     ' + N'--
  18351.     exec @retcode = dbo.sp_MSreplcheck_pull @publication = '+ quotename(@publication) + N'
  18352.     if (@retcode != 0 or @@error != 0)
  18353.         return -1
  18354.     '
  18355.     insert into #proctext(procedure_text) values(@cmd)
  18356. END                    
  18357. go
  18358.  
  18359. EXEC dbo.sp_MS_marksystemobject sp_MSscript_security
  18360. GO
  18361.  
  18362. raiserror('Creating procedure sp_MSscript_endproc', 0,1)
  18363. go
  18364. create procedure sp_MSscript_endproc (
  18365.     @objid int, 
  18366.     @op_type varchar(3) = 'ins', -- 'ins', 'upd', 'del'
  18367.     @columns binary(32),
  18368.     @outvars nvarchar(4000),
  18369.     @queued_pub bit = 0
  18370. )
  18371. as
  18372. BEGIN
  18373.     declare @cmd nvarchar(4000)
  18374.     declare @qualname nvarchar(512)
  18375.  
  18376.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  18377.  
  18378.     --
  18379.     -- start scripting
  18380.     --
  18381.     select @cmd = N'
  18382.     ' + N'--
  18383.     ' + N'-- decide the return code
  18384.     ' + N'--
  18385.     if (@execution_mode = @immediate)
  18386.     begin
  18387.         if @error != 0
  18388.               return -1
  18389.         -- Return special code to indicate the subscriber row needs to be
  18390.         -- refreshed.
  18391.         if @rowcount = 0
  18392.               return 5
  18393.     end'
  18394.     insert into #proctext(procedure_text) values(@cmd)
  18395.  
  18396.     --
  18397.     -- operation specific stuff
  18398.     --
  18399.     if (@queued_pub = 1)
  18400.     begin
  18401.         if (@op_type = 'ins')
  18402.         begin
  18403.             select @cmd = N'
  18404.     if (@execution_mode = @QFirstPass)
  18405.     begin
  18406.         if (@rowcount = 0)
  18407.         begin
  18408.             if (@error in (547, 2627))
  18409.                 return 2 -- insert conflict
  18410.             else
  18411.                 return -1 -- error
  18412.         end
  18413.     end'
  18414.         end
  18415.         else if (@op_type = 'upd')
  18416.         begin
  18417.             select @cmd = N'
  18418.     if (@execution_mode = @QFirstPass)
  18419.     begin
  18420.         if (@rowcount = 0)
  18421.         begin
  18422.             if (@error in (0, 547, 2627))
  18423.                 return 1 -- update conflict
  18424.             else
  18425.                 return -1 -- error
  18426.         end
  18427.     end'
  18428.         end
  18429.         else if (@op_type = 'del')
  18430.         begin
  18431.             select @cmd = N'
  18432.     if (@execution_mode = @QFirstPass)
  18433.     begin
  18434.         if (@rowcount = 0)
  18435.         begin
  18436.             if (@error in (0, 547))
  18437.                 return 3 -- delete conflict
  18438.             else
  18439.                 return -1 -- error
  18440.         end
  18441.     end'
  18442.         end
  18443.         insert into #proctext(procedure_text) values(@cmd)
  18444.         
  18445.         --
  18446.         -- continue with scripting
  18447.         --
  18448.         select @cmd = N'
  18449.     
  18450.     if (@execution_mode in (@QPubWins, @QSubWins))
  18451.     begin        
  18452.         if (@@error != 0 or @retcode != 0)
  18453.             return -1 -- error
  18454.     end
  18455.     '
  18456.         insert into #proctext(procedure_text) values(@cmd)
  18457.     end
  18458.  
  18459.     --
  18460.     -- if we have output vars to assign do it now
  18461.     --
  18462.     if (@outvars is not null)
  18463.     begin   
  18464.         if @op_type = 'upd'
  18465.         begin
  18466.             --
  18467.             -- Script out pk var assigment that used in sp_MSscript_where_clause
  18468.             --
  18469.             exec dbo.sp_MSscript_pkvar_assignment @objid, @columns, 1
  18470.             insert into #proctext(procedure_text) values(N'
  18471.     ')
  18472.         end
  18473.  
  18474.         select @cmd = N'
  18475.     select ' + @outvars + N'
  18476.     from ' + @qualname 
  18477.         insert into #proctext(procedure_text) values( @cmd)
  18478.         insert into #proctext(procedure_text) values( N'
  18479.     ')
  18480.     
  18481.         if (@op_type = 'ins')
  18482.             exec dbo.sp_MSscript_where_clause @objid, @columns, 'new pk', null, 4
  18483.         else if (@op_type = 'upd')
  18484.             exec dbo.sp_MSscript_where_clause @objid, @columns, 'old pk', null, 4
  18485.     end
  18486.  
  18487.     --
  18488.     -- Final part of the proc
  18489.     --
  18490.     select @cmd = N'
  18491.     
  18492.     ' + N'--
  18493.     ' + N'-- past all checks
  18494.     ' + N'--
  18495.     return 0
  18496. END
  18497. '
  18498.     insert into #proctext(procedure_text) values(@cmd)
  18499.     
  18500.     --
  18501.     -- all done
  18502.     --
  18503.     return 0
  18504. END
  18505. go
  18506.  
  18507. EXEC dbo.sp_MS_marksystemobject sp_MSscript_endproc
  18508. GO
  18509.  
  18510.  
  18511. raiserror('Creating procedure sp_MStable_not_modifiable', 0,1)
  18512. go
  18513. create proc sp_MStable_not_modifiable
  18514.     @objid   int,
  18515.     @columns binary(32)
  18516. as
  18517.     declare @colname      sysname
  18518.     declare @typestring   nvarchar(4000)
  18519.     declare @this_col     int
  18520.     declare @art_col      int
  18521.     declare @isset        int
  18522.     declare @found int, @repl_columns int
  18523.  
  18524.     select @art_col = 1
  18525.     select @found = 0, @repl_columns = 0
  18526.  
  18527.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  18528.     select colid from syscolumns where id = @objid order by colid asc
  18529.  
  18530.     OPEN hCColid
  18531.  
  18532.     FETCH hCColid INTO @this_col
  18533.  
  18534.     WHILE (@@fetch_status <> -1)
  18535.     begin
  18536.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  18537.  
  18538.         if @isset != 0 and EXISTS (select name from syscolumns where id=@objid and @this_col=colid and iscomputed<>1)
  18539.         begin
  18540.             select @repl_columns = @repl_columns + 1
  18541.             exec dbo.sp_MSget_type @objid, @this_col, @colname output, @typestring OUTPUT
  18542.  
  18543.             if @typestring = N'timestamp' or ColumnProperty(@objid, @colname, 'IsIdentity') = 1
  18544.                 select @found = 1
  18545.  
  18546.         end
  18547.         FETCH hCColid INTO @this_col
  18548.     end
  18549.     CLOSE hCColid
  18550.     DEALLOCATE hCColid
  18551.  
  18552.     if @found = 1 and @repl_columns = 1
  18553.         return 1
  18554.     else
  18555.         return 0
  18556. go
  18557.  
  18558.  
  18559. EXEC dbo.sp_MS_marksystemobject sp_MStable_not_modifiable
  18560. GO
  18561.  
  18562. --
  18563. -- proc to script the various checks done for queued and
  18564. -- synctran execution prior to actual detection/resolution
  18565. -- For queued execution, we also check for Reinitialization
  18566. -- phase
  18567. --
  18568. raiserror('Creating procedure sp_MSscript_ExecutionMode_stmt', 0,1)
  18569. go
  18570. create procedure sp_MSscript_ExecutionMode_stmt (
  18571.     @publication sysname, 
  18572.     @article     sysname,
  18573.     @proctype    int = 0)        -- 0 insert, 1 delete, 2 update
  18574. as
  18575. begin
  18576.     declare @cmd        nvarchar(4000)
  18577.             ,@artid        int
  18578.             ,@pubid        int
  18579.             ,@queued_pub bit
  18580.  
  18581.     select @pubid = pubid, @queued_pub = allow_queued_tran 
  18582.         from syspublications where name = @publication
  18583.     select @artid = artid from sysarticles where name = @article and pubid = @pubid
  18584.  
  18585.     --
  18586.     -- For queued execution check if we are in the phase of reinitialization
  18587.     --
  18588.     select @cmd = N'
  18589.     ' + N'--
  18590.     ' + N'-- Check if we are in the process of Reinitialization
  18591.     ' + N'-- if yes then return
  18592.     ' + N'--' 
  18593.     insert into #proctext(procedure_text) values( @cmd )
  18594.  
  18595.     select @cmd = N'
  18596.     exec @retcode = dbo.sp_MSgetarticlereinitvalue @orig_server, @orig_db, ' + 
  18597.     cast(@artid as nvarchar(5)) + N', @reinit output
  18598.     if (@retcode != 0 or @@error != 0)
  18599.         return -1 '
  18600.     insert into #proctext(procedure_text) values( @cmd )
  18601.  
  18602.     select @cmd = N'
  18603.     if (@reinit = 1) -- Resync state
  18604.     begin
  18605.         if (@execution_mode = @immediate)
  18606.             return -2'
  18607.     if (@queued_pub = 1)
  18608.     begin
  18609.         select @cmd = @cmd + N'
  18610.         else
  18611.             return 4 -- Queued Resync state'
  18612.     end
  18613.     select @cmd = @cmd + N'
  18614.     end
  18615.     '
  18616.     insert into #proctext(procedure_text) values( @cmd )
  18617.     
  18618.     --
  18619.     -- set loopback detection for immediate
  18620.     --
  18621.     select @cmd = N'
  18622.     if (@execution_mode = @immediate)
  18623.     begin
  18624.         ' + N'--
  18625.         ' + N'-- For immediate
  18626.         ' + N'-- enable loopback detection
  18627.         ' + N'--
  18628.         exec @retcode = dbo.sp_replsetoriginator @orig_server, @orig_db
  18629.         if (@retcode != 0 or @@error != 0) 
  18630.             return -1
  18631.     end'
  18632.     insert into #proctext(procedure_text) values( @cmd )
  18633.  
  18634.     /********* no need to disable since we never enable
  18635.     if (@queued_pub = 1)
  18636.     begin
  18637.         --
  18638.         -- disable loopback for queued
  18639.         --
  18640.         select @cmd = N'
  18641.     else if (@execution_mode in (@QFirstPass, @QSubWins))
  18642.     begin
  18643.         ' + N'--
  18644.         ' + N'-- For queued
  18645.         ' + N'-- disable loopback detection
  18646.         ' + N'--
  18647.         exec @retcode = dbo.sp_replsetoriginator N''anull'', N''anull''
  18648.         if (@retcode != 0 or @@error != 0) 
  18649.             return -1
  18650.     end'
  18651.         insert into #proctext(procedure_text) values( @cmd )
  18652.     end
  18653.     **********/
  18654.  
  18655.     if (@queued_pub = 1)
  18656.     begin
  18657.         --
  18658.         -- Queued reinitialization mode execution
  18659.         --
  18660.         select @cmd = N'
  18661.     else if (@execution_mode = @QReinit)
  18662.     begin
  18663.         ' + N'--
  18664.         ' + N'-- For Queued reinitialization
  18665.         ' + N'-- Set the Queue and subscription for reinit
  18666.         ' + N'--'
  18667.         insert into #proctext(procedure_text) values( @cmd )
  18668.  
  18669.         select @cmd = N'
  18670.         exec @retcode = dbo.sp_reinitsubscription @publication = ''' 
  18671.             + master.dbo.fn_MSgensqescstr(@publication) collate database_default + N''', @article = ''' +  
  18672.             master.dbo.fn_MSgensqescstr(@article) collate database_default + N''', @subscriber = @orig_server, @destination_db = @orig_db
  18673.         if (@retcode != 0 or @@error != 0)
  18674.             return -1
  18675.         else
  18676.             return 0
  18677.     end'
  18678.  
  18679.         insert into #proctext(procedure_text) values( @cmd )
  18680.     end
  18681.  
  18682.     --
  18683.     -- all done
  18684.     --
  18685.     return 0
  18686. end 
  18687. go
  18688. EXEC dbo.sp_MS_marksystemobject sp_MSscript_ExecutionMode_stmt
  18689. GO
  18690.  
  18691. raiserror('Creating procedure sp_MSscript_sync_ins_proc', 0,1)
  18692. go
  18693. create procedure sp_MSscript_sync_ins_proc (
  18694.     @publication sysname, 
  18695.     @article     sysname,
  18696.     @procname    sysname)
  18697. as
  18698. BEGIN
  18699.     declare @source_objid int
  18700.             ,@colname sysname
  18701.             ,@indid int
  18702.             ,@cmd          nvarchar(4000)
  18703.             ,@columns      binary(32)
  18704.             ,@outvars      nvarchar(4000)
  18705.             ,@rc           int
  18706.             ,@error_cmd    tinyint
  18707.             ,@identity_insert bit
  18708.             ,@queued_pub bit
  18709.  
  18710.     set nocount on
  18711.     --
  18712.     -- Create temp table
  18713.     --
  18714.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  18715.     select @queued_pub = allow_queued_tran from syspublications where name = @publication
  18716.  
  18717.     --
  18718.     -- proc definition
  18719.     --
  18720.     exec @rc = dbo.sp_MSscript_beginproc @publication, @article, @procname, @source_objid output, @columns output
  18721.     if @rc = 0
  18722.         return
  18723.  
  18724.     --
  18725.     -- construct parameter list
  18726.     --
  18727.     exec dbo.sp_MSscript_params @source_objid, @columns, null, 1,  @outvars output
  18728.  
  18729.     --
  18730.     -- add other parameters and start body of proc
  18731.     --
  18732.     exec dbo.sp_MSscript_procbodystart @queued_pub
  18733.  
  18734.     --
  18735.     -- script out security check
  18736.     --
  18737.     exec dbo.sp_MSscript_security @publication
  18738.  
  18739.     --
  18740.     -- script the execution mode checks
  18741.     --
  18742.     exec dbo.sp_MSscript_ExecutionMode_stmt @publication, @article, 0
  18743.  
  18744.     --
  18745.     -- script out subscription validation
  18746.     --
  18747.     exec dbo.sp_MSscript_validate_subscription @publication, @article
  18748.  
  18749.     --
  18750.     -- Work around for case where article has 1 col that is not user-modfied (identity, timestamp)
  18751.     -- *** Do we need to check this here - 
  18752.     -- *** we should be checking this when creating subscription
  18753.     -- 
  18754.     exec @rc = dbo.sp_MStable_not_modifiable @source_objid, @columns
  18755.     if @rc = 1
  18756.         select @error_cmd = 1
  18757.     else
  18758.     begin
  18759.         exec @indid = dbo.sp_MStable_has_unique_index @source_objid 
  18760.         if (@outvars != null and @indid = 0)
  18761.             -- no insert/update allowed if timestamp/identity col and no unique index
  18762.             select @error_cmd = 1
  18763.         else
  18764.             select @error_cmd = 0        
  18765.     end
  18766.  
  18767.     if (@error_cmd = 0)
  18768.     begin
  18769.         -- Continue generation
  18770.     
  18771.         -- Check to see if identity insert must be turned on
  18772.         -- i.e. Does the table has identity that are included in the partition?
  18773.         exec sp_MSis_identity_insert @publication, @article, @identity_insert output
  18774.         --
  18775.         -- script insert statemnt
  18776.         --
  18777.         exec dbo.sp_MSscript_insert_statement @source_objid, @columns, @identity_insert, @queued_pub
  18778.  
  18779.         --
  18780.         -- script queued specific stuff
  18781.         --
  18782.         if (@queued_pub = 1)
  18783.         begin
  18784.             --
  18785.             -- script Conflict resolution block for Subscriber Wins case
  18786.             --
  18787.             exec dbo.sp_MSscript_insert_subwins @publication, @article, @source_objid, @columns, @identity_insert
  18788.  
  18789.             --
  18790.             -- script Conflict resolution block for Publisher Wins case
  18791.             --
  18792.             exec dbo.sp_MSscript_insert_pubwins @publication, @article, @source_objid, @columns
  18793.         end
  18794.         
  18795.         --
  18796.         -- script closing 
  18797.         --
  18798.         exec dbo.sp_MSscript_endproc @source_objid, 'ins', @columns, @outvars, @queued_pub
  18799.     end
  18800.     else
  18801.     begin
  18802.         --
  18803.         -- Generate error command and finish
  18804.         --
  18805.         insert into #proctext(procedure_text) values( N'
  18806.     exec sp_MSreplraiserror 20516
  18807. END
  18808. ')
  18809.     end
  18810.                   
  18811.     --
  18812.     -- send fragments to client
  18813.     --
  18814.     select procedure_text from #proctext order by c1 asc
  18815. END
  18816. go
  18817.  
  18818. EXEC dbo.sp_MS_marksystemobject sp_MSscript_sync_ins_proc
  18819. GO
  18820.  
  18821. raiserror('Creating procedure sp_MSscript_sync_upd_proc', 0,1)
  18822. go
  18823. create procedure sp_MSscript_sync_upd_proc (
  18824.     @publication sysname, 
  18825.     @article     sysname,
  18826.     @procname    sysname)
  18827. as
  18828. BEGIN
  18829.     declare @source_objid int
  18830.             ,@colname sysname
  18831.             ,@indid int
  18832.             ,@cmd          nvarchar(4000)
  18833.             ,@columns      binary(32)
  18834.             ,@outvars      nvarchar(4000)
  18835.             ,@rc           int
  18836.             ,@error_cmd    tinyint
  18837.             ,@identity_insert bit
  18838.             ,@queued_pub bit
  18839.  
  18840.     set nocount on
  18841.     --
  18842.     -- Create temp table
  18843.     --
  18844.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  18845.     select @queued_pub = allow_queued_tran from syspublications where name = @publication
  18846.  
  18847.     --
  18848.     -- proc definition
  18849.     --
  18850.     exec @rc = dbo.sp_MSscript_beginproc @publication, @article, @procname, @source_objid output, @columns output
  18851.     if @rc = 0
  18852.         return
  18853.  
  18854.     --
  18855.     -- construct parameter list
  18856.     -- Script bitmap parameter
  18857.     --
  18858.     exec dbo.sp_MSscript_params @source_objid, @columns, null, 1,  @outvars output
  18859.     insert into #proctext(procedure_text) values( N',')
  18860.     exec dbo.sp_MSscript_params @source_objid, @columns, N'_old', 0, null
  18861.     insert into #proctext(procedure_text) values( N'
  18862.     ,@bitmap varbinary(4000)')
  18863.  
  18864.     --
  18865.     -- add other parameters and start body of proc
  18866.     --
  18867.     exec dbo.sp_MSscript_procbodystart @queued_pub 
  18868.  
  18869.     --
  18870.     -- script out security check
  18871.     --
  18872.     exec dbo.sp_MSscript_security @publication
  18873.  
  18874.     --
  18875.     -- script the execution mode checks
  18876.     --
  18877.     exec dbo.sp_MSscript_ExecutionMode_stmt @publication, @article, 2
  18878.  
  18879.     --
  18880.     -- script out subscription validation
  18881.     --
  18882.     exec dbo.sp_MSscript_validate_subscription @publication, @article
  18883.  
  18884.     --
  18885.     -- Work around for case where article has 1 col that is not user-modfied (identity, timestamp)
  18886.     -- *** Do we need to check this here - 
  18887.     -- *** we should be checking this when creating subscription
  18888.     -- 
  18889.     exec @rc = dbo.sp_MStable_not_modifiable @source_objid, @columns
  18890.     if @rc = 1
  18891.         select @error_cmd = 1
  18892.     else
  18893.     begin
  18894.         exec @indid = dbo.sp_MStable_has_unique_index @source_objid 
  18895.         if (@outvars != null and @indid = 0)
  18896.             -- no insert/update allowed if timestamp/identity col and no unique index
  18897.             select @error_cmd = 1
  18898.         else
  18899.             select @error_cmd = 0        
  18900.     end
  18901.  
  18902.     if (@error_cmd = 0)
  18903.     begin
  18904.         -- Continue generation
  18905.         
  18906.         --
  18907.         -- script update statemnt
  18908.         --
  18909.         exec dbo.sp_MSscript_update_statement @publication, @article, @source_objid, @columns, @queued_pub
  18910.  
  18911.         --
  18912.         -- script queued specific stuff
  18913.         --
  18914.         if (@queued_pub = 1)
  18915.         begin
  18916.             -- Check to see if identity insert must be turned on
  18917.             -- i.e. Does the table has identity that are included in the partition?
  18918.             exec sp_MSis_identity_insert @publication, @article, @identity_insert output
  18919.             --
  18920.             --
  18921.             -- script Conflict resolution block for Subscriber Wins case
  18922.             --
  18923.             exec dbo.sp_MSscript_update_subwins @publication, @article, @source_objid, @columns, @identity_insert
  18924.  
  18925.             --
  18926.             -- script Conflict resolution block for Publisher Wins case
  18927.             --
  18928.             exec dbo.sp_MSscript_update_pubwins @publication, @article, @source_objid, @columns
  18929.         end
  18930.  
  18931.         --
  18932.         -- script closing 
  18933.         --
  18934.         exec dbo.sp_MSscript_endproc @source_objid, 'upd', @columns, @outvars, @queued_pub
  18935.     end
  18936.     else
  18937.     begin
  18938.         --
  18939.         -- Generate error command and finish
  18940.         --
  18941.         insert into #proctext(procedure_text) values( N'
  18942.     exec sp_MSreplraiserror 20516
  18943. END
  18944. ')
  18945.     end
  18946.                   
  18947.     --
  18948.     -- send fragments to client
  18949.     --
  18950.     select procedure_text from #proctext order by c1 asc
  18951. END
  18952. go
  18953.  
  18954. EXEC dbo.sp_MS_marksystemobject sp_MSscript_sync_upd_proc
  18955. GO
  18956.  
  18957. raiserror('Creating procedure sp_MSscript_sync_del_proc', 0,1)
  18958. go
  18959. create procedure sp_MSscript_sync_del_proc (
  18960.     @publication sysname, 
  18961.     @article     sysname,
  18962.     @procname    sysname)
  18963. as
  18964. BEGIN
  18965.     declare @source_objid int
  18966.     declare @colname sysname
  18967.     declare @indid int
  18968.     declare @cmd          nvarchar(4000)
  18969.     declare @columns      binary(32)
  18970.     declare @outvars      nvarchar(4000)
  18971.     declare @rc           int
  18972.     declare @error_cmd    tinyint
  18973.     declare @queued_pub bit
  18974.  
  18975.     set nocount on
  18976.     --
  18977.     -- Create temp table
  18978.     --
  18979.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  18980.     select @queued_pub = allow_queued_tran from syspublications where name = @publication
  18981.  
  18982.     --
  18983.     -- proc definition
  18984.     --
  18985.     exec @rc = dbo.sp_MSscript_beginproc @publication, @article, @procname, @source_objid output, @columns output
  18986.     if @rc = 0
  18987.         return
  18988.  
  18989.     --
  18990.     -- construct parameter list
  18991.     --
  18992.     exec dbo.sp_MSscript_params @source_objid, @columns, N'_old', 0, null
  18993.  
  18994.     --
  18995.     -- add other parameters and start body of proc
  18996.     --
  18997.     exec dbo.sp_MSscript_procbodystart @queued_pub 
  18998.  
  18999.     --
  19000.     -- script out security check
  19001.     --
  19002.     exec dbo.sp_MSscript_security @publication
  19003.  
  19004.     --
  19005.     -- script the execution mode checks
  19006.     --
  19007.     exec dbo.sp_MSscript_ExecutionMode_stmt @publication, @article, 1
  19008.  
  19009.     --
  19010.     -- script out subscription validation
  19011.     --
  19012.     exec dbo.sp_MSscript_validate_subscription @publication, @article
  19013.  
  19014.     --
  19015.     -- Work around for case where article has 1 col that is not user-modfied (identity, timestamp)
  19016.     -- *** Do we need to check this here - 
  19017.     -- *** we should be checking this when creating subscription
  19018.     -- 
  19019.     exec @rc = dbo.sp_MStable_not_modifiable @source_objid, @columns
  19020.     if @rc = 1
  19021.         select @error_cmd = 1
  19022.     else
  19023.     begin
  19024.         exec @indid = dbo.sp_MStable_has_unique_index @source_objid 
  19025.         if (@outvars != null and @indid = 0)
  19026.             -- no insert/update allowed if timestamp/identity col and no unique index
  19027.             select @error_cmd = 1
  19028.         else
  19029.             select @error_cmd = 0        
  19030.     end
  19031.  
  19032.     if (@error_cmd = 0)
  19033.     begin
  19034.         -- Continue generation
  19035.         
  19036.         --
  19037.         -- script delete statemnt
  19038.         --
  19039.         exec dbo.sp_MSscript_delete_statement @publication, @article, @source_objid, @columns, @queued_pub
  19040.  
  19041.         --
  19042.         -- script queued specific stuff
  19043.         --
  19044.         if (@queued_pub = 1)
  19045.         begin
  19046.             --
  19047.             -- script Conflict resolution block for Subscriber Wins case
  19048.             --
  19049.             exec dbo.sp_MSscript_delete_subwins @publication, @article, @source_objid, @columns
  19050.  
  19051.             --
  19052.             -- script Conflict resolution block for Publisher Wins case
  19053.             --
  19054.             exec dbo.sp_MSscript_delete_pubwins @publication, @article, @source_objid, @columns
  19055.         end
  19056.         
  19057.         --
  19058.         -- script closing 
  19059.         --
  19060.         exec dbo.sp_MSscript_endproc @source_objid, 'del', @columns, @outvars, @queued_pub
  19061.     end
  19062.     else
  19063.     begin
  19064.         --
  19065.         -- Generate error command and finish
  19066.         --
  19067.         insert into #proctext(procedure_text) values( N'
  19068.     exec sp_MSreplraiserror 20516
  19069. END
  19070. ')
  19071.     end
  19072.                   
  19073.     --
  19074.     -- send fragments to client
  19075.     --
  19076.     select procedure_text from #proctext order by c1 asc
  19077.  
  19078. END
  19079. go
  19080.  
  19081. EXEC dbo.sp_MS_marksystemobject sp_MSscript_sync_del_proc
  19082. GO
  19083.  
  19084. raiserror('Creating procedure sp_MSscript_pub_upd_trig', 0,1)
  19085. go
  19086. create procedure sp_MSscript_pub_upd_trig
  19087.     @publication sysname, 
  19088.     @article     sysname,
  19089.     @procname    sysname
  19090. as
  19091.     declare @cmd       nvarchar(4000)
  19092.     declare @qualname  nvarchar(512)
  19093.     declare @objid       int
  19094.     declare @columns   binary(32)
  19095.  
  19096.     set nocount on
  19097.  
  19098.     -- Create temp table
  19099.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  19100.  
  19101.  
  19102.     -- Retrieve underlying table name and replicated columns
  19103.     select @objid = objid, @columns = columns from sysarticles a, syspublications p
  19104.         where a.name = @article and
  19105.               p.name = @publication and
  19106.               a.pubid = p.pubid
  19107.  
  19108.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  19109.  
  19110.     -- Trigger should be invoked for repl processes as well.
  19111.     select @cmd = N'create trigger ' + QUOTENAME(@procname) + N' on ' + @qualname + N' '
  19112.     select @cmd = @cmd + N'for update as ' 
  19113.  
  19114.     exec dbo.sp_MSflush_command @cmd output, 1
  19115.  
  19116.     insert into #proctext(procedure_text) values(N'
  19117. ')
  19118.     -- declare common local variables
  19119.     insert into #proctext(procedure_text) values 
  19120.         (N'declare @rc int
  19121. ')
  19122.     insert into #proctext(procedure_text) values(N'select @rc = @@ROWCOUNT 
  19123.  
  19124. ')
  19125.         
  19126.     -- Optimization. Return immediately if no row changed
  19127.     -- This must be at the beginning of the trigger to @@rowcount be overwritten.
  19128.     insert into #proctext(procedure_text) values(N'if @rc = 0 return 
  19129. ')
  19130.     insert into #proctext(procedure_text) values(N'if update (msrepl_tran_version) return 
  19131. ')
  19132.  
  19133.     -- update the version column of all the updated rows all at once.
  19134.     select @cmd = N'update ' + @qualname + N' set msrepl_tran_version = newid() from ' +
  19135.         @qualname + ', inserted '
  19136.     exec dbo.sp_MSflush_command @cmd output, 1
  19137.     insert into #proctext(procedure_text) values(N'
  19138. ')
  19139.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'version pk', null, 4
  19140.  
  19141.     insert into #proctext(procedure_text) values(N'
  19142. ')
  19143.     -- send fragments to client
  19144.     select procedure_text from #proctext order by c1 asc
  19145. go
  19146. EXEC dbo.sp_MS_marksystemobject sp_MSscript_pub_upd_trig
  19147. go
  19148.  
  19149. raiserror('Creating procedure sp_MSmakeconflicttable', 0,1)
  19150. go
  19151. create procedure sp_MSmakeconflicttable (
  19152.     @article sysname, 
  19153.     @publication sysname,
  19154.     @creation_mode bit = 0,     -- 0 = for publisher, 1 = for subscriber (snapshot)
  19155.     @is_debug bit = 0)    
  19156. as
  19157. begin
  19158.     --
  19159.     -- variables
  19160.     --
  19161.     declare @retcode    int
  19162.             ,@cmd        nvarchar(4000)
  19163.             ,@qualname    nvarchar(540)
  19164.             ,@basetablename nvarchar(540)
  19165.             ,@id         int
  19166.             ,@colid        int
  19167.             ,@colname    sysname
  19168.             ,@col        sysname
  19169.             ,@coltype    sysname
  19170.             ,@iscolnullable    bit
  19171.             ,@dbname        sysname
  19172.             ,@ownername    sysname
  19173.             ,@tablename    sysname
  19174.             ,@basetableid int
  19175.             ,@columns    varbinary(32)
  19176.             ,@isset        int
  19177.             ,@tabid        int
  19178.             ,@artid        int
  19179.             ,@pubid        int
  19180.             ,@indid        int
  19181.             ,@indkey        int
  19182.             ,@key        sysname
  19183.             ,@indexname    sysname
  19184.             ,@mode_publisher bit
  19185.             ,@mode_subscriber bit
  19186.             ,@is_queued bit
  19187.  
  19188.     set nocount on
  19189.     select @dbname = db_name()
  19190.     select @mode_publisher = 0, @mode_subscriber = 1
  19191.  
  19192.     --
  19193.     -- Check and make sure the base table exists
  19194.     --
  19195.     select    @artid = a.artid, @basetableid = a.objid, 
  19196.             @basetablename = object_name(a.objid), @columns = a.columns, 
  19197.             @pubid = a.pubid, @is_queued = NULLIF(p.allow_queued_tran, 0)
  19198.     from sysarticles a, syspublications p
  19199.     where    a.name = @article and
  19200.             p.name = @publication and
  19201.             a.pubid = p.pubid
  19202.     if (@basetableid is null or @basetableid = 0)
  19203.     begin
  19204.         raiserror('sp_MSmakeconflicttable(debug): bad basetableid = %d', 16, 1, @basetableid)
  19205.         return (1)
  19206.     end
  19207.  
  19208.     --
  19209.     -- If the publication does not allowed queued tran, return
  19210.     --
  19211.     if (@is_queued != 1)
  19212.         return 0
  19213.  
  19214.     --
  19215.     -- get the article owner
  19216.     --
  19217.     select @ownername = user_name(o.uid) 
  19218.     from sysobjects o , sysarticles a 
  19219.     where    o.id=a.objid and 
  19220.             a.name=@article
  19221.  
  19222.     --
  19223.     -- base table should be owner qualified
  19224.     --
  19225.     select @basetablename = QUOTENAME(@ownername) + N'.' + QUOTENAME(@basetablename)
  19226.     
  19227.     --
  19228.     -- Prepare the name for the Conflict table, index
  19229.     --
  19230.     if (@creation_mode = @mode_publisher)
  19231.     begin
  19232.         --
  19233.         -- creating on publisher - get unique names for table, index
  19234.         --
  19235.         exec @retcode = sp_MSgettranconflictname @publication=@publication, 
  19236.                             @source_object=@basetablename, 
  19237.                             @str_prefix='conflict_', 
  19238.                             @conflict_table=@tablename OUTPUT
  19239.         if (@retcode != 0 or @@error != 0)
  19240.         begin
  19241.             raiserror('sp_MSmakeconflicttable(debug): sp_MSgettranconflictname failed for cft name', 16, 1)
  19242.             return (1)
  19243.         end
  19244.  
  19245.         exec @retcode = sp_MSgettranconflictname @publication=@publication, 
  19246.                             @source_object=@basetablename, 
  19247.                             @str_prefix='cftind_', 
  19248.                             @conflict_table=@indexname OUTPUT
  19249.         if (@retcode != 0 or @@error != 0)
  19250.         begin
  19251.             raiserror('sp_MSmakeconflicttable(debug): sp_MSgettranconflictname failed for cft index', 16, 1)
  19252.             return (1)
  19253.         end
  19254.     end
  19255.     else
  19256.     begin
  19257.         --
  19258.         -- Get the destination owner
  19259.         --
  19260.         select    @ownername = dest_owner
  19261.         from sysarticles 
  19262.         where artid = @artid and pubid = @pubid
  19263.         
  19264.         --
  19265.         -- creating for subscriber, get the names from existing
  19266.         -- table on publisher
  19267.         --
  19268.         select @id = conflict_tableid, @tablename = OBJECT_NAME(conflict_tableid) 
  19269.         from sysarticleupdates
  19270.         where artid = @artid and pubid = @pubid
  19271.  
  19272.         exec @indid = dbo.sp_MStable_has_unique_index @id
  19273.         if (@indid = 0)
  19274.         begin
  19275.             raiserror('sp_MSmakeconflicttable(debug): no unique index for cft table', 16, 1)
  19276.             return (1)
  19277.         end
  19278.             
  19279.         select @indexname = name
  19280.         from sysindexes 
  19281.         where indid = @indid and id = @id
  19282.     end
  19283.     
  19284.     --
  19285.     -- Qualify the Conflict tablename
  19286.     --
  19287.     select @qualname = case 
  19288.         when (@ownername is null or @ownername = ' ') then QUOTENAME(@tablename)
  19289.                 else QUOTENAME(@ownername) + '.' + QUOTENAME(@tablename) end
  19290.  
  19291.     --
  19292.     -- To check if specified object exists in current database drop it if it exists
  19293.     -- Do this only if we are creating for Publisher
  19294.     --
  19295.     if (@creation_mode = @mode_publisher)
  19296.     begin
  19297.         select @id = object_id(@qualname)
  19298.         if @id is not NULL
  19299.         begin
  19300.             execute( N'drop table ' + @qualname )
  19301.             if (@@error != 0)
  19302.             begin
  19303.                 raiserror('sp_MSmakeconflicttable(debug): could not drop cft table', 16, 1)
  19304.                 return (1)
  19305.             end
  19306.         end
  19307.     end
  19308.  
  19309.     --
  19310.     -- begin tran
  19311.     --
  19312.     begin tran sp_MSmakeconflicttable
  19313.  
  19314.     --
  19315.     -- create table to select the command text out of
  19316.     --
  19317.     if exists (select * from sysobjects where name = 'tempcmd' and uid = user_id('dbo'))
  19318.         drop table dbo.tempcmd
  19319.         
  19320.     create table dbo.tempcmd (step int identity NOT NULL, cmdtext nvarchar(4000) NULL)
  19321.  
  19322.     if (@creation_mode = @mode_subscriber)
  19323.     begin
  19324.         select @cmd = N'DROP TABLE ' + @qualname + N'
  19325. '
  19326.         insert into dbo.tempcmd(cmdtext) values(@cmd)
  19327.         insert into dbo.tempcmd(cmdtext) values(N'GO
  19328. ')        
  19329.     end
  19330.     
  19331.     select @cmd = N'CREATE TABLE ' + @qualname + N'('
  19332.     insert into dbo.tempcmd(cmdtext) values(@cmd)
  19333.  
  19334.     --
  19335.     -- Declare the cursor to get info on each column of base table
  19336.     --
  19337.     declare #hcurColumnInfo cursor local FAST_FORWARD FOR
  19338.         select colid,
  19339.         isnullable
  19340.         from syscolumns
  19341.         where iscomputed = 0 and id=@basetableid 
  19342.         order by colid
  19343.     FOR READ ONLY
  19344.  
  19345.     select @cmd = NULL
  19346.     open #hcurColumnInfo
  19347.     fetch #hcurColumnInfo into @colid, @iscolnullable
  19348.     while (@@FETCH_STATUS = 0)
  19349.     begin
  19350.         -- Check if this column is included for replication
  19351.         if (@columns is null)
  19352.             select @isset = 1
  19353.         else
  19354.             exec @isset = dbo.sp_isarticlecolbitset @colid, @columns
  19355.  
  19356.         -- Get the typestring for this column
  19357.         -- Skip this column if it is NULL
  19358.         if ( @isset != 0 )
  19359.         begin        
  19360.             exec @retcode = dbo.sp_MSget_type @basetableid, @colid, @colname output, @coltype OUTPUT
  19361.             if (@@ERROR!= 0 or @retcode != 0)
  19362.             begin
  19363.                 raiserror('sp_MSmakeconflicttable(debug): sp_MSget_type failed', 16, 1)
  19364.                 rollback tran sp_MSmakeconflicttable
  19365.                 return (1)
  19366.             end
  19367.  
  19368.             if (@coltype IS NULL)
  19369.                 select @isset = 0
  19370.         end
  19371.             
  19372.         -- process the column ?
  19373.         if ( @isset != 0 )
  19374.         begin        
  19375.             -- Initialize
  19376.             if (@cmd is NULL)
  19377.                 select @cmd = N'    '
  19378.             else
  19379.                 select @cmd = N'    ,'
  19380.  
  19381.             -- Create the column info
  19382.             select @cmd = @cmd + quotename(@colname) + N' ' 
  19383.             select @cmd = @cmd + @coltype
  19384.             
  19385.             -- Apply nullability
  19386.             if (@iscolnullable = 1)
  19387.                 select @cmd = @cmd + N' NULL'
  19388.             else
  19389.                 select @cmd = @cmd + N' NOT NULL'
  19390.  
  19391.             -- insert into the temptable
  19392.             insert into dbo.tempcmd(cmdtext) values(@cmd)
  19393.         end
  19394.  
  19395.         -- do the next fetch
  19396.         fetch #hcurColumnInfo into @colid, @iscolnullable
  19397.     end
  19398.  
  19399.     close #hcurColumnInfo
  19400.     deallocate #hcurColumnInfo
  19401.  
  19402.     --
  19403.     -- Now add the conflict related columns
  19404.     --
  19405.     insert into dbo.tempcmd(cmdtext) values(N'    ,origin_datasource nvarchar(255) NULL
  19406.     ,conflict_type int NULL
  19407.     ,reason_code int NULL
  19408.     ,reason_text nvarchar(720) NULL
  19409.     ,pubid int NULL
  19410.     ,tranid nvarchar(40) NULL
  19411.     ,insertdate datetime NOT NULL
  19412.     ,qcfttabrowid uniqueidentifier DEFAULT NEWID() NOT NULL)
  19413.     ')
  19414.  
  19415.     --
  19416.     -- Create an unique index - we add some more fields to the index of base table
  19417.     --
  19418.     exec @indid = dbo.sp_MStable_has_unique_index @basetableid
  19419.     if (@indid = 0)
  19420.     begin
  19421.         raiserror('sp_MSmakeconflicttable(debug): no unique index for base table', 16, 1)
  19422.         rollback tran sp_MSmakeconflicttable
  19423.         return (1)
  19424.     end
  19425.  
  19426.     if (@creation_mode = @mode_subscriber)
  19427.     begin
  19428.         insert into dbo.tempcmd(cmdtext) values(N'GO
  19429. ')        
  19430.     end
  19431.  
  19432.     insert into dbo.tempcmd(cmdtext) values(N'
  19433.     CREATE UNIQUE INDEX ' + quotename(@indexname) + ' ON ' +  @qualname  + N'(')
  19434.  
  19435.     select @cmd = NULL
  19436.     select @indkey = 1
  19437.     while (@indkey <= 16)
  19438.     begin    
  19439.         select @key = index_col(@basetablename, @indid, @indkey)
  19440.         if (@key is not null)
  19441.         begin
  19442.             -- make sure we are replicating this column
  19443.             if (@columns is null)
  19444.                 select @isset = 1
  19445.             else
  19446.             begin
  19447.                 -- map the index to the right column in base table
  19448.                 exec dbo.sp_MSget_col_position @basetableid, @columns, @key, @col output, @colid output
  19449.                 exec @isset = dbo.sp_isarticlecolbitset @colid, @columns
  19450.             end
  19451.                 
  19452.             if (@isset = 1)
  19453.             begin
  19454.                 if (@cmd is NULL)
  19455.                     select @cmd = quotename(@key)
  19456.                 else
  19457.                     select @cmd = @cmd + N', ' + quotename(@key)
  19458.             end
  19459.         end
  19460.         select @indkey = @indkey + 1
  19461.     end
  19462.     
  19463.     --
  19464.     -- Add two more fields in the index
  19465.     --
  19466.     if (@cmd is NULL)
  19467.         select @cmd = N'tranid, qcfttabrowid'
  19468.     else
  19469.         select @cmd = @cmd + N', tranid, qcfttabrowid'
  19470.     insert into dbo.tempcmd(cmdtext) values(@cmd + N')')
  19471.  
  19472.     --
  19473.     -- If we are creating on publisher
  19474.     -- create the table now and update sysarticleupdates now
  19475.     --
  19476.     if (@creation_mode = @mode_publisher)
  19477.     begin
  19478.         if (@is_debug = 0)
  19479.         begin
  19480.             --
  19481.             -- create the table now
  19482.             --
  19483.             select @cmd = 'select cmdtext from dbo.tempcmd order by step'
  19484.             exec @retcode = master..xp_execresultset @cmd, @dbname
  19485.             if (@@error != 0 or @retcode != 0)
  19486.             begin
  19487.                 raiserror('sp_MSmakeconflicttable(debug): xp_execresultset failed', 16, 1)
  19488.                 rollback tran sp_MSmakeconflicttable
  19489.                 return (1)
  19490.             end
  19491.  
  19492.             --
  19493.             -- update sysarticleupdates
  19494.             --
  19495.             select @tabid = id from sysobjects where name = @tablename
  19496.             if (@tabid = 0 or @tabid is NULL)
  19497.             begin
  19498.                 raiserror('sp_MSmakeconflicttable(debug): cft table not created after xp_execresultset', 16, 1)
  19499.                 rollback tran sp_MSmakeconflicttable
  19500.                 return (1)
  19501.             end
  19502.             else
  19503.             begin
  19504.                 update dbo.sysarticleupdates set conflict_tableid = @tabid
  19505.                     where artid = @artid and pubid = @pubid
  19506.  
  19507.                 -- mark the table as system object
  19508.                 if (@ownername in ('dbo','INFORMATION_SCHEMA'))
  19509.                 begin
  19510.                     exec @retcode = dbo.sp_MS_marksystemobject @tablename
  19511.                     if (@@error != 0 or @retcode != 0)
  19512.                     begin
  19513.                         -- roll back the tran
  19514.                         raiserror('sp_MSmakeconflicttable(debug): sp_MS_marksystemobject exec failed for cft table', 16, 1)
  19515.                         rollback tran sp_MSmakeconflicttable
  19516.                         return (1)
  19517.                     end
  19518.                 end
  19519.             end
  19520.         end
  19521.         else
  19522.             select cmdtext from dbo.tempcmd order by step
  19523.     end
  19524.  
  19525.     --
  19526.     -- commit the tran
  19527.     --
  19528.     commit tran    
  19529.  
  19530.     --
  19531.     -- If we are creating for subscriber then
  19532.     -- just to a select on the temp table
  19533.     --
  19534.     if (@creation_mode = @mode_subscriber)
  19535.     begin
  19536.         select cmdtext from dbo.tempcmd order by step
  19537.     end
  19538.  
  19539.     -- drop the table we created
  19540.     drop table dbo.tempcmd
  19541.     return 0
  19542. end
  19543. go
  19544. exec dbo.sp_MS_marksystemobject sp_MSmakeconflicttable 
  19545. go
  19546.  
  19547. dump tran master with no_log
  19548. go
  19549.  
  19550. --
  19551. -- sp_scriptsubconflicttable
  19552. --
  19553. -- This proc is used when the user is creating a nosync queued subscription.
  19554. -- It generates the script for creating conflict table on subscriber for a 
  19555. -- given queued subscription article. The SP is executed on the publisher.publisher_db 
  19556. -- and it generates the script which is executed on the subscriber.subscriber_db
  19557. -- See the docs for more information on creation of nosync queued subscription.
  19558. -- 
  19559. -- Parameters:
  19560. --    @publication    sysname - name of publication we are subscribing to
  19561. --    @article    sysname - name of the subscribed article
  19562. --
  19563. -- Return :
  19564. --    0 if successfull, 1 otherwise
  19565. --
  19566. -- Rowset
  19567. --    Return script to create the conflict table for the given article
  19568. --
  19569. print ''
  19570. print 'Creating procedure sp_scriptsubconflicttable'
  19571. go
  19572. create proc sp_scriptsubconflicttable (
  19573.     @publication sysname
  19574.     ,@article sysname
  19575.     )
  19576. as
  19577. begin
  19578.     declare @retcode int
  19579.  
  19580.     --
  19581.     -- Security Check.
  19582.     --
  19583.     exec @retcode = dbo.sp_MSreplcheck_publish
  19584.     if (@@error != 0 or @retcode != 0)
  19585.         return (1)
  19586.  
  19587.     --
  19588.     -- Parameter Check: @publication.
  19589.     -- The @publication cannot be NULL and must conform to the rules
  19590.     -- for identifiers.
  19591.     --
  19592.     if (@publication IS NULL)
  19593.     begin
  19594.         raiserror (14043, 16, 2, '@publication')
  19595.         return (1)
  19596.     end
  19597.     exec @retcode = dbo.sp_validname @publication
  19598.     if (@retcode != 0)
  19599.         return (1)
  19600.  
  19601.     --
  19602.     -- Parameter Check: @article.
  19603.     -- The @article cannot be NULL and must conform to the rules
  19604.     -- for identifiers.
  19605.     --    
  19606.     if @article IS NULL
  19607.     begin
  19608.         raiserror (14043, 16, 3, '@article')
  19609.         return (1)
  19610.     end
  19611.     exec @retcode = dbo.sp_MSreplcheck_name @article
  19612.     if (@@error != 0 or @retcode != 0)
  19613.         return (1)
  19614.  
  19615.     if LOWER(@article) = 'all'
  19616.     begin
  19617.         raiserror (14032, 16, 2, '@article')
  19618.         return (1)
  19619.     end
  19620.  
  19621.     --
  19622.     -- now call the SP to generate the script
  19623.     --
  19624.     exec @retcode = dbo.sp_MSmakeconflicttable @article, @publication, 1
  19625.     return @retcode
  19626. end
  19627. go
  19628.  
  19629. EXEC dbo.sp_MS_marksystemobject sp_scriptsubconflicttable
  19630. GO
  19631.  
  19632. print ''
  19633. print 'Creating procedure sp_MSgen_sync_tran_procs'
  19634. go
  19635. create procedure sp_MSgen_sync_tran_procs (
  19636.     @publication    sysname,        -- table name 
  19637.     @article        sysname,
  19638.     @ins_proc       sysname,
  19639.     @upd_proc       sysname,
  19640.     @del_proc       sysname,
  19641.     @upd_trig        sysname
  19642. )
  19643. as
  19644. begin
  19645.     set nocount on
  19646.  
  19647.     declare @cmd nvarchar(4000)
  19648.             ,@procname nvarchar(517)
  19649.             ,@dbname sysname
  19650.             ,@owner sysname
  19651.             ,@retcode int
  19652.  
  19653.     select @owner = user_name(o.uid) from sysobjects o , sysarticles a where o.id=a.objid and a.name=@article
  19654.  
  19655.     -- We are now going to create procs, so start a transaction
  19656.     begin tran gen_procs
  19657.         
  19658.         -- Call out to individual create proc routines      
  19659.         select @dbname = db_name()
  19660.         select @cmd = N'sp_MSscript_sync_ins_proc ''' + master.dbo.fn_MSgensqescstr(@publication) collate database_default + 
  19661.                 N''', ''' + master.dbo.fn_MSgensqescstr(@article) collate database_default  + 
  19662.                 N''', ''' + master.dbo.fn_MSgensqescstr(@ins_proc) collate database_default + N''''
  19663.         exec @retcode = master.dbo.xp_execresultset @cmd, @dbname
  19664.         if (@@error != 0 or @retcode != 0)
  19665.         begin
  19666.             rollback tran gen_procs
  19667.             return 1
  19668.         end
  19669.  
  19670.         select @cmd = N'sp_MSscript_sync_upd_proc ''' + master.dbo.fn_MSgensqescstr(@publication) collate database_default + 
  19671.                 N''', ''' + master.dbo.fn_MSgensqescstr(@article) collate database_default + 
  19672.                 N''', ''' + master.dbo.fn_MSgensqescstr(@upd_proc) collate database_default + N''''
  19673.         exec @retcode = master.dbo.xp_execresultset @cmd, @dbname
  19674.         if (@@error != 0 or @retcode != 0)
  19675.         begin
  19676.             rollback tran gen_procs
  19677.             return 1
  19678.         end
  19679.  
  19680.         select @cmd = N'sp_MSscript_sync_del_proc ''' + master.dbo.fn_MSgensqescstr(@publication) collate database_default + 
  19681.                 N''', ''' + master.dbo.fn_MSgensqescstr(@article) collate database_default  + 
  19682.                 N''', ''' + master.dbo.fn_MSgensqescstr(@del_proc) collate database_default + N''''
  19683.         exec @retcode = master.dbo.xp_execresultset @cmd, @dbname
  19684.         if (@@error != 0 or @retcode != 0)
  19685.         begin
  19686.             rollback tran gen_procs
  19687.             return 1
  19688.         end
  19689.  
  19690.         select @cmd = N'sp_MSscript_pub_upd_trig ''' + master.dbo.fn_MSgensqescstr(@publication) collate database_default + 
  19691.                 N''', ''' + master.dbo.fn_MSgensqescstr(@article) collate database_default  + 
  19692.                 N''', ''' + master.dbo.fn_MSgensqescstr(@upd_trig) collate database_default + N''''
  19693.         exec @retcode = master.dbo.xp_execresultset @cmd, @dbname
  19694.         if (@@error != 0 or @retcode != 0)
  19695.         begin
  19696.             rollback tran gen_procs
  19697.             return 1
  19698.         end
  19699.  
  19700.         -- Grant permissions
  19701.         select @cmd = 'grant exec on ' + quotename(@owner) + '.' + quotename(@ins_proc) + ' to public'
  19702.         exec (@cmd)
  19703.         if (@@error != 0)
  19704.         begin
  19705.             rollback tran gen_procs
  19706.             return 1
  19707.         end
  19708.         select @cmd = 'grant exec on ' + quotename(@owner) + '.' + quotename(@upd_proc) + ' to public'
  19709.         exec (@cmd)
  19710.         if (@@error != 0)
  19711.         begin
  19712.             rollback tran gen_procs
  19713.             return 1
  19714.         end
  19715.         select @cmd = 'grant exec on ' + quotename(@owner) + '.' + quotename(@del_proc) + ' to public'
  19716.         exec (@cmd)
  19717.         if (@@error != 0)
  19718.         begin
  19719.             rollback tran gen_procs
  19720.             return 1
  19721.         end
  19722.  
  19723.         -- Mark procedures as system procs so they don't show up in the UI
  19724.         if @owner in ('dbo','INFORMATION_SCHEMA')
  19725.         begin
  19726.             select @procname = @owner + '.' + @ins_proc
  19727.             exec @retcode = dbo.sp_MS_marksystemobject @procname
  19728.             if (@@error != 0 or @retcode != 0)
  19729.             begin
  19730.                 rollback tran gen_procs
  19731.                 return 1
  19732.             end
  19733.             select @procname = @owner + '.' + @upd_proc
  19734.             exec @retcode = dbo.sp_MS_marksystemobject @procname
  19735.             if (@@error != 0 or @retcode != 0)
  19736.             begin
  19737.                 rollback tran gen_procs
  19738.                 return 1
  19739.             end
  19740.             select @procname = @owner + '.' + @del_proc
  19741.             exec @retcode = dbo.sp_MS_marksystemobject @procname
  19742.             if (@@error != 0 or @retcode != 0)
  19743.             begin
  19744.                 rollback tran gen_procs
  19745.                 return 1
  19746.             end
  19747.             select @procname = @owner + '.' + @upd_trig
  19748.             exec @retcode = dbo.sp_MS_marksystemobject @procname
  19749.             if (@@error != 0 or @retcode != 0)
  19750.             begin
  19751.                 rollback tran gen_procs
  19752.                 return 1
  19753.             end
  19754.         end
  19755.  
  19756.         -- Mark procedures to set 'NOT FOR REPL' bit
  19757.         select @procname = @owner + '.' + @ins_proc
  19758.         exec @retcode = dbo.sp_MSmark_proc_norepl @procname
  19759.         if (@@error != 0 or @retcode != 0)
  19760.         begin
  19761.             rollback tran gen_procs
  19762.             return 1
  19763.         end
  19764.         select @procname = @owner + '.' + @upd_proc
  19765.         exec @retcode = dbo.sp_MSmark_proc_norepl @procname
  19766.         if (@@error != 0 or @retcode != 0)
  19767.         begin
  19768.             rollback tran gen_procs
  19769.             return 1
  19770.         end
  19771.         select @procname = @owner + '.' + @del_proc
  19772.         exec @retcode = dbo.sp_MSmark_proc_norepl @procname
  19773.         if (@@error != 0 or @retcode != 0)
  19774.         begin
  19775.             rollback tran gen_procs
  19776.             return 1
  19777.         end
  19778.  
  19779.     -- Commit tran
  19780.     commit tran
  19781. end
  19782. go
  19783.  
  19784. EXEC dbo.sp_MS_marksystemobject sp_MSgen_sync_tran_procs
  19785. GO
  19786.  
  19787. print ''
  19788. print 'Creating procedure sp_articlesynctranprocs'
  19789. go
  19790.  
  19791. CREATE PROCEDURE sp_articlesynctranprocs
  19792.     @publication sysname,         -- publication name 
  19793.     @article sysname,              -- article name 
  19794.     @ins_proc sysname,       -- name of sproc supporting Sync Tran inserts associated with this article
  19795.     @upd_proc sysname,       -- name of sproc supporting Sync Tran updates associated with this article
  19796.     @del_proc sysname,       -- name of sproc supporting Sync Tran deletes associated with this article
  19797.     @autogen       nvarchar(5) = 'true', -- indicates wether or not to auto generate sprocs
  19798.     @upd_trig sysname
  19799. AS
  19800.     SET NOCOUNT ON
  19801.  
  19802.     -- Declarations.
  19803.     DECLARE @pubid int
  19804.     DECLARE @artid int
  19805.     DECLARE @retcode int
  19806.     DECLARE @autogen_id bit
  19807.     DECLARE @ins_proc_id int
  19808.     DECLARE @upd_proc_id int
  19809.     DECLARE @del_proc_id int
  19810.     DECLARE @upd_trig_id int
  19811.     
  19812.     /* 
  19813.     ** Security Check.
  19814.     */
  19815.     exec @retcode = dbo.sp_MSreplcheck_publish
  19816.     if @@ERROR <> 0 or @retcode <> 0
  19817.         return(1)
  19818.     
  19819.     -- Parameter Check: @article. The @article name cannot be NULL and must conform 
  19820.     -- to the rules for identifiers.
  19821.     IF @article IS NULL
  19822.         BEGIN
  19823.             RAISERROR (14043, 16, -1, '@article')
  19824.             RETURN (1)
  19825.         END
  19826.  
  19827.     EXECUTE @retcode = dbo.sp_validname @article
  19828.     IF @retcode <> 0
  19829.         RETURN(1)
  19830.     
  19831.     -- Parameter Check: @publication.
  19832.     -- The @publication name cannot be NULL and must conform to the rules
  19833.     -- for identifiers.
  19834.     IF @publication IS NULL
  19835.         BEGIN
  19836.             RAISERROR (14043, 16, -1, '@publication')
  19837.             RETURN (1)
  19838.         END
  19839.  
  19840.     EXECUTE @retcode = dbo.sp_validname @publication
  19841.     IF @retcode <> 0
  19842.         RETURN (1)
  19843.  
  19844.     -- Parameter Check: @ins_proc, @upd_proc, @del_proc, @upd_trig
  19845.     -- The sproc names cannot be NULL and must conform to the rules
  19846.     -- for identifiers
  19847.  
  19848.     IF @ins_proc IS NULL
  19849.         BEGIN
  19850.             RAISERROR (14043, 16, -1, '@ins_proc')
  19851.             RETURN (1)
  19852.         END
  19853.  
  19854.     EXECUTE @retcode = dbo.sp_validname @ins_proc
  19855.     IF @retcode <> 0
  19856.         RETURN (1)
  19857.  
  19858.     IF @upd_proc IS NULL
  19859.         BEGIN
  19860.             RAISERROR (14043, 16, -1, '@upd_proc')
  19861.             RETURN (1)
  19862.         END
  19863.  
  19864.     EXECUTE @retcode = dbo.sp_validname @upd_proc
  19865.     IF @retcode <> 0
  19866.         RETURN (1)
  19867.  
  19868.     IF @del_proc IS NULL
  19869.         BEGIN
  19870.             RAISERROR (14043, 16, -1, '@del_proc')
  19871.             RETURN (1)
  19872.         END
  19873.  
  19874.     EXECUTE @retcode = dbo.sp_validname @del_proc
  19875.     IF @retcode <> 0
  19876.         RETURN (1)
  19877.  
  19878.     IF @upd_trig IS NULL
  19879.         BEGIN
  19880.             RAISERROR (14043, 16, -1, '@upd_trig')
  19881.             RETURN (1)
  19882.         END
  19883.  
  19884.     EXECUTE @retcode = dbo.sp_validname @upd_trig
  19885.     IF @retcode <> 0
  19886.         RETURN (1)
  19887.  
  19888.     -- Parameter Check:  @autogen
  19889.     IF @autogen IS NULL OR LOWER(@autogen collate SQL_Latin1_General_CP1_CS_AS) NOT IN ('true', 'false')
  19890.     BEGIN
  19891.         RAISERROR (14148, 16, -1, '@autogen')
  19892.         RETURN (1)
  19893.     END
  19894.  
  19895.     IF LOWER(@autogen collate SQL_Latin1_General_CP1_CS_AS) = 'true' 
  19896.         SELECT @autogen_id = 1
  19897.     ELSE 
  19898.         SELECT @autogen_id = 0
  19899.  
  19900.     -- Retrieve pubid & artid
  19901.     SELECT @pubid = a.pubid, @artid = a.artid 
  19902.     FROM sysarticles a, syspublications p
  19903.     WHERE p.name = @publication AND a.name = @article AND
  19904.         a.pubid = p.pubid
  19905.     IF @pubid IS NULL OR @artid IS NULL
  19906.     BEGIN
  19907.         if @pubid IS NULL RAISERROR (20026, 16, 1, @publication)
  19908.         if @artid IS NULL RAISERROR (20026, 16, 1, @publication)
  19909.         RETURN (1)
  19910.     END
  19911.  
  19912.        BEGIN TRAN sp_articlesynctranprocs
  19913.  
  19914.         -- if @autogen is true, generate the sprocs
  19915.         IF @autogen_id = 1
  19916.         BEGIN
  19917.             EXECUTE @retcode =  dbo.sp_MSgen_sync_tran_procs @publication, @article, 
  19918.                 @ins_proc, @upd_proc, @del_proc, @upd_trig
  19919.             IF @retcode <> 0
  19920.             BEGIN
  19921.                 IF @@TRANCOUNT <> 0
  19922.                     ROLLBACK tran sp_articlesynctranprocs
  19923.                 RETURN (1)
  19924.             END
  19925.         END
  19926.  
  19927.         --retrieve sproc id's, fail if they don't exist
  19928.         SELECT @ins_proc_id = id FROM sysobjects WHERE name = @ins_proc
  19929.         SELECT @upd_proc_id = id FROM sysobjects WHERE name = @upd_proc
  19930.         SELECT @del_proc_id = id FROM sysobjects WHERE name = @del_proc
  19931.         select @upd_trig_id = id FROM sysobjects WHERE name = @upd_trig
  19932.  
  19933.         IF (@ins_proc_id IS NULL) OR (@upd_proc_id IS NULL) OR (@del_proc_id IS NULL) OR
  19934.             (@upd_trig_id IS NULL)             
  19935.         BEGIN
  19936.             if @ins_proc_id IS NULL RAISERROR (20500, 16, 1, @ins_proc)
  19937.             if @upd_proc_id IS NULL RAISERROR (20500, 16, 1, @upd_proc)
  19938.             if @del_proc_id IS NULL RAISERROR (20500, 16, 1, @del_proc)
  19939.             if @upd_trig_id IS NULL RAISERROR (20500, 16, 1, @upd_trig)
  19940.             IF @@TRANCOUNT <> 0
  19941.                 ROLLBACK tran sp_articlesynctranprocs
  19942.             RETURN (1)
  19943.         END
  19944.  
  19945.         -- perform insert into sysarticleupdates
  19946.         -- need to mark this as a system table, so this sproc can live in master db
  19947.         INSERT sysarticleupdates(pubid, artid, sync_ins_proc, sync_upd_proc, sync_del_proc, autogen, sync_upd_trig)
  19948.             VALUES (@pubid, @artid, @ins_proc_id, @upd_proc_id, @del_proc_id, @autogen_id, @upd_trig_id)
  19949.  
  19950.         IF @@ERROR <> 0
  19951.             BEGIN
  19952.                 IF @@TRANCOUNT <> 0
  19953.                     ROLLBACK tran sp_articlesynctranprocs
  19954.                 RETURN (1)
  19955.             END
  19956.  
  19957.     COMMIT TRAN
  19958. go
  19959.  
  19960. EXEC dbo.sp_MS_marksystemobject sp_articlesynctranprocs
  19961. GO
  19962.  
  19963. print ''
  19964. print 'Creating procedure sp_reinitsubscription'
  19965. go
  19966.  
  19967. CREATE PROCEDURE sp_reinitsubscription (
  19968.     @publication sysname = 'all',    /* publication name */
  19969.     @article sysname = 'all',        /* article name */
  19970.     -- Force user to specify the subscriber name
  19971.     @subscriber sysname,             /* subscriber name */
  19972.     @destination_db sysname = 'all'   /* destination database name */
  19973.     ,@for_schema_change bit = 0
  19974. ) AS
  19975.  
  19976.     DECLARE @retcode int
  19977.     DECLARE @distributor sysname
  19978.     DECLARE @distribdb sysname
  19979.     declare @active tinyint
  19980.     declare @subscribed tinyint
  19981.     declare @automatic tinyint
  19982.     DECLARE @artid int
  19983.     DECLARE @distproc nvarchar (255)
  19984.     DECLARE @dbname sysname
  19985.     DECLARE @sub_ts binary(10) -- must be binary(10) type.
  19986.     DECLARE @sync_type tinyint
  19987.     DECLARE @immediate_sync bit
  19988.     DECLARE @subscription_type int
  19989.     DECLARE @push int
  19990.     DECLARE @pub sysname
  19991.     DECLARE @dest_db sysname
  19992.     DECLARE @sub_name sysname
  19993.     DECLARE @art_name sysname
  19994.     DECLARE @none tinyint
  19995.     declare @login_name sysname
  19996.  
  19997.  
  19998.   
  19999.     -- Initialization
  20000.     select @active = 2
  20001.     select @subscribed = 1
  20002.     select @dbname = DB_NAME()
  20003.     SELECT @none = 2            /* Const: synchronization type 'none' */
  20004.     SELECT @automatic = 1       /* Const: synchronization type 'automatic' */
  20005.     select @push = 0
  20006.  
  20007.     /* 
  20008.     ** Security Check.
  20009.     ** We use login_name stored in syssubscriptions to manage security 
  20010.     */
  20011.  
  20012.     /* Validate names */
  20013.  
  20014.     EXECUTE @retcode = dbo.sp_validname @publication
  20015.     IF @@ERROR <> 0 OR @retcode <> 0
  20016.         RETURN (1)
  20017.  
  20018.     /* article name can be a quoted name
  20019.     EXECUTE @retcode = dbo.sp_validname @article
  20020.     IF @@ERROR <> 0 OR @retcode <> 0
  20021.         RETURN (1)
  20022.     */
  20023.  
  20024.     -- Subscriber can be NULL
  20025.     IF @subscriber IS NOT NULL
  20026.     BEGIN
  20027.         EXECUTE @retcode = dbo.sp_validname @subscriber
  20028.         IF @@ERROR <> 0 OR @retcode <> 0
  20029.             RETURN (1)
  20030.  
  20031.         EXECUTE @retcode = dbo.sp_validname @destination_db
  20032.         IF @@ERROR <> 0 OR @retcode <> 0
  20033.             RETURN (1)
  20034.     END
  20035.  
  20036.     -- Replace 'all' with '%'
  20037.     if LOWER(@publication) = 'all'
  20038.         SELECT @publication = '%'
  20039.  
  20040.     if LOWER(@article) = 'all'
  20041.         SELECT @article = '%'
  20042.  
  20043.     if LOWER(@subscriber) = 'all'
  20044.         SELECT @subscriber = '%'
  20045.  
  20046.     if LOWER(@destination_db) = 'all'
  20047.         SELECT @destination_db = '%'
  20048.  
  20049.     /*
  20050.     ** Parameter Check:  @publication
  20051.     ** Check to make sure that the publication exists, that it's not NULL,
  20052.     ** and that it conforms to the rules for identifiers.
  20053.     */
  20054.     IF NOT EXISTS (SELECT * FROM syspublications WHERE name LIKE @publication)
  20055.         BEGIN
  20056.         IF @publication = '%'
  20057.                 RAISERROR (14008, 11, -1)
  20058.         ELSE
  20059.                 RAISERROR (20026, 11, -1, @publication)
  20060.         RETURN (1)
  20061.         END
  20062.  
  20063.     /*
  20064.     ** Parameter Check:  @article
  20065.     ** Check to make sure that the article exists, that it's not null,
  20066.     ** and that it conforms to the rules for identifiers.
  20067.     */
  20068.     IF NOT EXISTS (SELECT *
  20069.                      FROM sysextendedarticlesview a,
  20070.                           syspublications b
  20071.                 WHERE a.name LIKE @article
  20072.                       AND a.pubid = b.pubid
  20073.                       AND b.name LIKE @publication)
  20074.  
  20075.         BEGIN
  20076.         IF @article = '%'
  20077.                 RAISERROR (14009, 11, -1, @publication)
  20078.         ELSE
  20079.                 RAISERROR (20027, 11, -1, @article)
  20080.         RETURN (1)
  20081.         END
  20082.  
  20083.     -- Don't check subscriber and dest_db for virtual subscriptions
  20084.     IF @subscriber IS NOT NULL and @subscriber <> N'%'
  20085.     BEGIN    
  20086.         /*
  20087.         ** Parameter Check:  @subscriber
  20088.         ** Check to make sure that the subscriber exists
  20089.         */
  20090.         select @subscriber = UPPER(@subscriber)
  20091.         
  20092.         IF NOT EXISTS (SELECT *
  20093.                          FROM master..sysservers
  20094.                         WHERE UPPER(srvname) = UPPER(@subscriber) collate database_default
  20095.                           AND (srvstatus & 4) <> 0)
  20096.  
  20097.             BEGIN
  20098.                 RAISERROR (14063, 11, -1)
  20099.                 RETURN (1)
  20100.             END
  20101.     END
  20102.  
  20103.     -- Wrong dest_db will be caught by the following query
  20104.  
  20105.     -- Check to make sure the subscription exists 
  20106.     IF  @publication <> '%' AND
  20107.         @subscriber <> '%' AND
  20108.  
  20109.         NOT EXISTS (SELECT *
  20110.           FROM syssubscriptions sub,
  20111.                sysextendedarticlesview art,
  20112.                syspublications pub,
  20113.                master..sysservers ss
  20114.          WHERE pub.name LIKE @publication collate database_default
  20115.            AND art.name LIKE @article collate database_default
  20116.            AND ((UPPER(ss.srvname) = UPPER(@subscriber) collate database_default
  20117.            AND sub.srvid = ss.srvid)
  20118.            OR (@subscriber is NULL 
  20119.            AND pub.allow_anonymous = 1))
  20120.            AND sub.artid = art.artid
  20121.            AND art.pubid = pub.pubid
  20122.            AND ((@destination_db = N'%') OR (sub.dest_db = @destination_db collate database_default)))
  20123.     BEGIN
  20124.         RAISERROR (14055, 16, -1)
  20125.         RETURN (1)
  20126.     END
  20127.  
  20128.     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  20129.                                        @distribdb = @distribdb OUTPUT
  20130.     IF @retcode <> 0 OR @@ERROR <> 0
  20131.         RETURN (1)
  20132.  
  20133.     IF @distribdb IS NULL OR @distributor IS NULL
  20134.     BEGIN
  20135.         RAISERROR (14071, 16, -1)
  20136.         RETURN (1)
  20137.     END
  20138.  
  20139.     DECLARE hCresyncsub CURSOR LOCAL FAST_FORWARD FOR
  20140.         -- non immediate_sync pubs
  20141.         SELECT pub.name,
  20142.                pub.immediate_sync,
  20143.                art.name,
  20144.                ss.srvname,
  20145.                sub.dest_db,
  20146.                sub.sync_type,
  20147.                sub.subscription_type,
  20148.                sub.login_name
  20149.           FROM syssubscriptions sub,
  20150.                sysextendedarticlesview art,
  20151.                syspublications pub,
  20152.                master..sysservers ss
  20153.          WHERE pub.name LIKE @publication
  20154.            AND art.name LIKE @article
  20155.            AND ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber) collate database_default))
  20156.            AND sub.srvid = ss.srvid
  20157.            AND sub.artid = art.artid
  20158.            AND art.pubid = pub.pubid
  20159.            AND ((@destination_db = N'%') OR (sub.dest_db = @destination_db collate database_default))
  20160.            AND sub.status = @active
  20161.            AND pub.immediate_sync = 0
  20162.         
  20163.         UNION
  20164.         -- Immediate_sync pubs
  20165.         SELECT DISTINCT
  20166.                pub.name,
  20167.                immediate_sync,
  20168.                -- If @article is '%', do publication level operation.
  20169.                -- otherwise, do article level
  20170.                case @article 
  20171.                     when '%' then '%'
  20172.                     else art.name
  20173.                     end, 
  20174.                ss.srvname,
  20175.                sub.dest_db,
  20176.                sub.sync_type,
  20177.                sub.subscription_type,
  20178.                sub.login_name
  20179.           FROM syssubscriptions sub,
  20180.                sysextendedarticlesview art,
  20181.                syspublications pub,
  20182.                master..sysservers ss
  20183.          WHERE pub.name LIKE @publication collate database_default -- Ignore @article
  20184.            AND art.name LIKE @article collate database_default
  20185.            AND ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber) collate database_default))
  20186.            AND sub.srvid = ss.srvid
  20187.            AND sub.artid = art.artid
  20188.            AND art.pubid = pub.pubid
  20189.            AND ((@destination_db = N'%') OR (sub.dest_db = @destination_db collate database_default))
  20190.            AND sub.status = @active
  20191.            AND pub.immediate_sync = 1
  20192.                  
  20193.         UNION
  20194.         -- For anonymous subscribers or attached subscriptions.
  20195.         SELECT DISTINCT pub.name,
  20196.                immediate_sync,
  20197.                -- If @article is '%', do publication level operation.
  20198.                -- otherwise, do article level
  20199.                case @article 
  20200.                     when '%' then '%'
  20201.                     else art.name
  20202.                     end, -- art.name is '%' from immediate_sync pub
  20203.                CONVERT(sysname, NULL), -- subscriber name (null represent virtual)
  20204.                'virtual', -- destination_db for virtual subscription is hardcoded in 
  20205.                          -- sp_MSadd_subscription.
  20206.                @automatic, -- sub.sync_type is auto tor anonymous subscriber
  20207.                @push,      -- virtual subscription is push type,
  20208.                'sa'
  20209.           FROM syspublications pub,
  20210.                sysarticles art
  20211.          WHERE pub.name LIKE @publication -- Ignore @article
  20212.            AND art.name LIKE @article
  20213.            AND art.pubid = pub.pubid
  20214.            AND pub.immediate_sync = 1
  20215.            AND (@subscriber = '%' OR @subscriber IS NULL) 
  20216.                  
  20217.     FOR READ ONLY
  20218.  
  20219.     OPEN hCresyncsub 
  20220.  
  20221.     -- Note: Don't overwrite the variables used in the cursor.
  20222.     FETCH hCresyncsub INTO @pub, @immediate_sync, @art_name, @sub_name, 
  20223.         @dest_db, @sync_type, @subscription_type, @login_name
  20224.  
  20225.     WHILE (@@fetch_status <> -1)
  20226.     BEGIN
  20227.         -- Security Check
  20228.         IF  suser_sname(suser_sid()) <> @login_name AND is_srvrolemember('sysadmin') <> 1  
  20229.             AND is_member ('db_owner') <> 1
  20230.         BEGIN
  20231.                 RAISERROR (14126, 11, -1)
  20232.                 RETURN (1)
  20233.         END
  20234.  
  20235.         if @sync_type = @none
  20236.         begin
  20237.         raiserror(21071, 10, -1, @art_name, @sub_name, @dest_db, @pub)
  20238.         FETCH hCresyncsub INTO @pub, @immediate_sync, @art_name, @sub_name, 
  20239.             @dest_db, @sync_type, @subscription_type, @login_name
  20240.         continue
  20241.         end
  20242.  
  20243.         begin tran
  20244.         save TRAN sp_reinitsubscription
  20245.  
  20246.         -- Reset subscription status to subscribed.
  20247.         -- It will be reactivated later as following:
  20248.         -- 1. Well known on non immediate_sync: it need to be reactivated by snapshot agent
  20249.         -- 2. Well known on immediate_sync: it will be reactivated laster in 
  20250.         -- this stored procedure to the state of virtual subscription. The status will be 
  20251.         -- active if the virtual subscription is active.
  20252.         -- 3. Anonymous (on immediate_sync by design): Only reset the status to subscribed
  20253.         -- if a single article is reinited or there's a schema change on the article. 
  20254.         -- (refer to sp_MSreinit_article.) In this case, the status will be reactivated by
  20255.         -- snapshot agent. If the whole publication is reinited and it is not for a schema 
  20256.         -- change, we don't need to do this 
  20257.         -- since the anonymous agent will automatically pick up latest snapshots after
  20258.         -- we reset the subscription guid later.
  20259.  
  20260.         -- If @sub_name is null, we are resetting anonymous subscriptions.
  20261.         -- Don't do this when reiniting anonymous subscription on whole publication.
  20262.         IF not (@sub_name IS NULL and @article = '%') or @for_schema_change = 1
  20263.         BEGIN
  20264.             EXEC @retcode = dbo.sp_changesubstatus
  20265.                 @publication = @pub,
  20266.                 @article = @art_name,
  20267.                 @subscriber = @sub_name,
  20268.                 @destination_db = @dest_db,
  20269.                 @status = 'subscribed'
  20270.             IF @@ERROR <> 0 OR @retcode <> 0
  20271.             BEGIN
  20272.                 CLOSE hCresyncsub
  20273.                 DEALLOCATE hCresyncsub
  20274.                 RAISERROR (14070, 16, -1)
  20275.                 GOTO UNDO
  20276.             END
  20277.         END
  20278.  
  20279.         -- Don't do this when reiniting a single article.
  20280.         -- Reset the subscription guid at the distributor for immediate_sync publication.
  20281.          -- Reset subscription creation datetime for all types of publication
  20282.         -- used by retention cleanup.
  20283.         if @article = '%'
  20284.         begin
  20285.             SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSreset_subscription'
  20286.             EXEC @retcode = @distproc 
  20287.                 @publisher = @@SERVERNAME, 
  20288.                 @publisher_db = @dbname, 
  20289.                 @publication = @pub,
  20290.                 @subscriber = @sub_name, 
  20291.                 @subscriber_db = @dest_db,
  20292.                 @subscription_type = @subscription_type
  20293.  
  20294.             IF @@ERROR <> 0 OR @retcode <> 0
  20295.             BEGIN
  20296.                 CLOSE hCresyncsub
  20297.                 DEALLOCATE hCresyncsub
  20298.                 GOTO UNDO
  20299.             END
  20300.         end
  20301.  
  20302.         -- Activate the subscription again if the publication is immediate_sync and
  20303.         -- the whole publication is reinitted.
  20304.         -- Otherwise, the snapshot agent will activate the subscription
  20305.         
  20306.         -- If this is for schema change, commands generated by the LR will be invalid
  20307.         -- until the new snapshot is generated and applied so DON'T reactivate. 
  20308.         -- Let the snapshot agent do it.
  20309.  
  20310.         --IF (@for_schema_change = 0 AND @immediate_sync = 1 AND @subscriber IS NOT NULL)
  20311.         IF (@for_schema_change = 0 and 
  20312.                 @immediate_sync = 1 AND 
  20313.                 @subscriber IS NOT NULL and 
  20314.                 @article = '%')
  20315.         BEGIN
  20316.             -- Set subscription status back to active again.
  20317.             EXEC @retcode = dbo.sp_changesubstatus
  20318.                 @publication = @pub,
  20319.                 @article = @art_name,
  20320.                 @subscriber = @sub_name,
  20321.                 @destination_db = @dest_db,
  20322.                 @status = 'active'
  20323.             IF @@ERROR <> 0 OR @retcode <> 0
  20324.             BEGIN
  20325.                 CLOSE hCresyncsub
  20326.                 DEALLOCATE hCresyncsub
  20327.                 RAISERROR (14070, 16, -1)
  20328.                 GOTO UNDO
  20329.             END
  20330.         END
  20331.         
  20332.         -- If article level reinit, reinit dependent articles in the publication as well    
  20333.         if @article <> '%'
  20334.         begin
  20335.             -- Reinit articles on which the current article depends on.
  20336.             declare @objid int, @pubid int, @srvid smallint,
  20337.                 @pre_creation_cmd tinyint
  20338.             select @pubid = pubid from syspublications where name = @pub
  20339.             select @objid = objid,
  20340.                     @pre_creation_cmd = pre_creation_cmd from sysarticles where 
  20341.                 pubid = @pubid and 
  20342.                 name = @art_name
  20343.             -- @sub_name is from sysservers, no need to upper it.
  20344.             select @srvid = srvid from master..sysservers where srvname = @sub_name collate database_default
  20345.             -- set virtual id if needed
  20346.             if @srvid is null
  20347.                 select @srvid = -1
  20348.  
  20349.             -- Have to use temp cursor name otherwise we will get a 'cursor already exists' error
  20350.             -- in recursive calls.
  20351.             DECLARE #hCdep CURSOR LOCAL FAST_FORWARD FOR
  20352.                 SELECT distinct art.name from sysextendedarticlesview art, syssubscriptions s where
  20353.                     art.pubid = @pubid and
  20354.                     s.artid = art.artid and
  20355.                     s.srvid = @srvid and
  20356.                     s.dest_db = @dest_db and
  20357.                     s.status = @active and
  20358.                     -- Has dri on referencing table or not
  20359.                     (convert(int, substring(art.schema_option, len(art.schema_option) - 2 + 1, 2)) & 0x00000200 <> 0 and
  20360.                       -- If the article schema option includes DRI, reinit articles that have 
  20361.                       -- forein key relationship on this table, have to do this
  20362.                       -- otherwise dist will fail because we cannot drop or delete base table.
  20363.                       exists ( select * from  sysreferences r where
  20364.                             r.rkeyid = @objid and
  20365.                             art.objid = r.fkeyid) or
  20366.                       -- If there's a schema bound view on this table, reinit that view etc.
  20367.                       -- We have to do this for schema bound view other wise, we cannot drop the table
  20368.                      -- Only do it if precreation command is 'drop table'
  20369.                      (@pre_creation_cmd = 1 and
  20370.                       exists ( select * from sysdepends d where
  20371.                             d.depid = @objid and
  20372.                             art.objid = d.id and
  20373.                             objectproperty(art.objid, 'IsSchemaBound') = 1)))
  20374.             FOR READ ONLY
  20375.  
  20376.             OPEN #hCdep
  20377.  
  20378.             -- Note: @art_name is changed
  20379.             FETCH #hCdep INTO @art_name
  20380.  
  20381.             WHILE (@@fetch_status <> -1)
  20382.             BEGIN
  20383.                 EXEC @retcode = dbo.sp_reinitsubscription
  20384.                     @publication = @pub,
  20385.                     @article = @art_name,
  20386.                     @subscriber = @sub_name,
  20387.                     @destination_db = @dest_db,
  20388.                     @for_schema_change = @for_schema_change
  20389.                 IF @@ERROR <> 0 OR @retcode <> 0
  20390.                     GOTO UNDO
  20391.                 FETCH #hCdep INTO @art_name
  20392.             END
  20393.             
  20394.             CLOSE #hCdep
  20395.             DEALLOCATE #hCdep
  20396.         end
  20397.     
  20398.         COMMIT TRAN 
  20399.  
  20400.         FETCH hCresyncsub INTO @pub, @immediate_sync, @art_name, @sub_name, 
  20401.             @dest_db, @sync_type, @subscription_type, @login_name
  20402.     END
  20403.  
  20404.     CLOSE hCresyncsub
  20405.     DEALLOCATE hCresyncsub
  20406.  
  20407.     RETURN(0)
  20408.  
  20409. UNDO:
  20410.     IF @@TRANCOUNT > 0
  20411.     begin
  20412.         ROLLBACK TRAN sp_reinitsubscription
  20413.         COMMIT TRAN
  20414.     end
  20415.     return 1
  20416. go
  20417.  
  20418. EXEC dbo.sp_MS_marksystemobject sp_reinitsubscription
  20419. GO
  20420.  
  20421. dump tran master with no_log
  20422. GO
  20423.  
  20424.  
  20425.  
  20426. --------------------------------------------------------------------
  20427. --------------------------------------------------------------------
  20428.  
  20429. print ''
  20430. print 'Creating procedure sp_MSareallcolumnscomputed'
  20431. go
  20432. create procedure sp_MSareallcolumnscomputed @tabid int, @colbitmap binary(32)
  20433. as
  20434. declare @isset int
  20435. declare @retcode int
  20436. declare @this_col int
  20437.  
  20438. select @retcode = 1
  20439.  
  20440. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  20441. select colid from syscolumns where id = @tabid order by colid asc
  20442.  
  20443. OPEN hCColid
  20444.  
  20445. FETCH hCColid INTO @this_col
  20446.  
  20447. WHILE (@@fetch_status <> -1)
  20448. BEGIN
  20449.     exec @isset = dbo.sp_isarticlecolbitset @this_col, @colbitmap
  20450.     if @isset != 0 and EXISTS (select name from syscolumns where id=@tabid and @this_col=colid and iscomputed<>1)
  20451.     BEGIN 
  20452.         select @retcode = 0
  20453.         break
  20454.     END
  20455.     FETCH hCColid INTO @this_col
  20456. END
  20457. CLOSE hCColid
  20458. DEALLOCATE hCColid
  20459.  
  20460. return @retcode
  20461. GO
  20462.  
  20463. EXEC dbo.sp_MS_marksystemobject sp_MSareallcolumnscomputed
  20464. GO
  20465. -----------------------------------------------------------
  20466. -----------------------------------------------------------
  20467.  
  20468. print ''
  20469. print 'Creating procedure sp_MSgettypestringudt'
  20470. go
  20471.  
  20472. create procedure sp_MSgettypestringudt @tabid int, @colid int, @typestring nvarchar(255) output
  20473. as
  20474. declare @coltypename sysname
  20475. declare @coltype  tinyint
  20476. declare @colusertype smallint
  20477. declare @collen   smallint
  20478. declare @colprec  tinyint
  20479. declare @colscale tinyint
  20480.  
  20481. select @coltypename = type_name( sc.xusertype ), @colusertype = sc.xusertype, @coltype = sc.xtype,
  20482.        @collen = sc.length, @colprec = sc.xprec, @colscale = sc.xscale
  20483. from syscolumns sc 
  20484. where sc.id = @tabid
  20485. and sc.colid = @colid
  20486. --and st.xtype = sc.xtype
  20487. --and st.xtype = st.xusertype
  20488.  
  20489. select @typestring = @coltypename
  20490.  
  20491. -- if it's not a user defined type, script out length/prec/scale as necessary
  20492. if @colusertype = @coltype 
  20493. begin
  20494.     if @coltypename in (N'char', N'varchar', N'binary', N'varbinary')
  20495.     begin
  20496.         select @typestring = @typestring + N'(' + convert(nvarchar,@collen) + N')'
  20497.     end
  20498.     else if @coltypename in (N'nchar', N'nvarchar' )
  20499.     begin
  20500.         select @typestring = @typestring + N'(' + convert(nvarchar,@collen/2) + N')'
  20501.     end
  20502.     else if @coltype = 108 or @coltype = 106
  20503.     begin
  20504.         select @typestring = @typestring + N'(' + convert(nvarchar,@colprec) + N',' + convert(nvarchar,@colscale) + N')'
  20505.     end
  20506.     else if @coltype = 189
  20507.     begin
  20508.         select @typestring = N'binary(8)'
  20509.     end
  20510. end
  20511.     
  20512. go
  20513.  
  20514. EXEC dbo.sp_MS_marksystemobject sp_MSgettypestringudt
  20515. GO
  20516.  
  20517. --------------------------------------------------------------------
  20518. --------------------------------------------------------------------
  20519.  
  20520. print ''
  20521. print 'Creating procedure sp_gettypestring'
  20522. go
  20523.  
  20524. create procedure sp_gettypestring @tabid int, @colid int, @typestring nvarchar(255) output
  20525. as
  20526. declare @coltypename sysname
  20527. declare @coltype  tinyint
  20528. declare @colvar   bit
  20529. declare @collen   smallint
  20530. declare @colprec  tinyint
  20531. declare @colscale tinyint
  20532.  
  20533. select @coltypename = st.name, @coltype = st.xtype, @colvar = st.variable, 
  20534.        @collen = sc.length, @colprec = sc.xprec, @colscale = sc.xscale
  20535. from systypes st, syscolumns sc 
  20536. where sc.id = @tabid
  20537. and sc.colid = @colid
  20538. and st.xtype = sc.xtype
  20539. and st.xtype = st.xusertype
  20540.  
  20541. select @typestring = @coltypename
  20542.  
  20543. if @coltypename in (N'char', N'varchar', N'binary', N'varbinary')
  20544. begin
  20545.     select @typestring = @typestring + N'(' + convert(nvarchar,@collen) + N')'
  20546. end
  20547. else if @coltypename in (N'nchar', N'nvarchar' )
  20548. begin
  20549.     select @typestring = @typestring + N'(' + convert(nvarchar,@collen/2) + N')'
  20550. end
  20551. else if @coltype = 108 or @coltype = 106
  20552. begin
  20553.     select @typestring = @typestring + N'(' + convert(nvarchar,@colprec) + N',' + convert(nvarchar,@colscale) + N')'
  20554. end
  20555. else if @coltype = 189
  20556. begin
  20557.     select @typestring = N'binary(8)'
  20558. end
  20559.     
  20560. go
  20561.  
  20562. EXEC dbo.sp_MS_marksystemobject sp_gettypestring
  20563. GO
  20564.  
  20565. --------------------------------------------------------------------
  20566. --------------------------------------------------------------------
  20567.  
  20568.  
  20569.  
  20570. --------------------------------------------------------------------
  20571. --------------------------------------------------------------------
  20572.  
  20573. print ''
  20574. print 'sp_scriptpkwhereclause'
  20575. go
  20576.  
  20577. create procedure sp_scriptpkwhereclause @src_objid int, @pkcolumns binary(32),
  20578. @prefix nvarchar(10) = N'@pkc',
  20579. @artcolumns binary(32) = NULL
  20580. as
  20581. declare @this_col int
  20582. declare @art_col int
  20583. declare @spacer nvarchar(10)
  20584. declare @isset int
  20585. declare @cmd nvarchar(4000)
  20586.  
  20587. -- create WHERE clause
  20588.  
  20589. select @art_col = 0
  20590. select @spacer = N' '
  20591. select @cmd = N'where'
  20592.  
  20593. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  20594. select colid from syscolumns where id = @src_objid order by colid asc
  20595.  
  20596. OPEN hCColid
  20597.  
  20598. FETCH hCColid INTO @this_col
  20599.  
  20600. WHILE (@@fetch_status <> -1)
  20601. begin
  20602.     if EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid)
  20603.     begin
  20604.         -- If @artcolumns is not null, it is called from 
  20605.         -- sp_scriptxupdproc or sp_scriptxdelproc
  20606.         -- Use counter in article column bitmap
  20607.         -- Otherwise use counter in pk bitmap
  20608.         if @artcolumns is not null
  20609.         begin
  20610.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  20611.             if @isset != 0
  20612.                 select @art_col = @art_col + 1
  20613.         end
  20614.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  20615.         if @isset != 0 
  20616.         begin
  20617.             if @artcolumns is null
  20618.                 select @art_col = @art_col + 1
  20619.             select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = ' + @prefix + convert( nvarchar, @art_col ) 
  20620.             select @spacer = N' and '
  20621.             if len( @cmd ) > 3000
  20622.             begin
  20623.                 insert into #proctext(procedure_text) values( @cmd )
  20624.                 select @cmd = N''
  20625.             end
  20626.         end
  20627.     end
  20628.     FETCH hCColid INTO @this_col
  20629. end
  20630. CLOSE hCColid
  20631. DEALLOCATE hCColid
  20632.  
  20633. insert into #proctext(procedure_text) values( @cmd )
  20634.  
  20635. go
  20636.  
  20637. EXEC dbo.sp_MS_marksystemobject sp_scriptpkwhereclause
  20638. GO
  20639.  
  20640. --------------------------------------------------------------------
  20641. --------------------------------------------------------------------
  20642.  
  20643. print ''
  20644. print 'sp_MSscript_missing_row_check'
  20645. go
  20646.  
  20647. create procedure sp_MSscript_missing_row_check 
  20648. as
  20649.  
  20650. -- Note this must be done immediately after the update or delete statement.
  20651. -- create WHERE clause
  20652.  
  20653. insert into #proctext(procedure_text) values( N'if @@rowcount = 0' )
  20654. begin
  20655.     insert into #proctext(procedure_text) values( N'    if @@microsoftversion>0x07320000' )
  20656.     insert into #proctext(procedure_text) values( N'        exec sp_MSreplraiserror 20598' )
  20657. end
  20658. go
  20659.  
  20660. EXEC dbo.sp_MS_marksystemobject sp_MSscript_missing_row_check
  20661. GO
  20662.  
  20663. --------------------------------------------------------------------
  20664. --------------------------------------------------------------------
  20665.  
  20666. print ''
  20667. print 'Create procedure sp_scriptupdateparams'
  20668. go
  20669.  
  20670. create procedure sp_scriptupdateparams @src_objid int, @artcolumns binary(32), 
  20671. @pkcolumns binary(32), -- If it is null we are called by sp_scriptxupdproc
  20672. @param_count int = NULL output
  20673. as
  20674. declare @this_col int
  20675. declare @art_col int
  20676. declare @spacer nvarchar(10)
  20677. declare @isset int
  20678. declare @cmd nvarchar(4000)
  20679. declare @typestring nvarchar(255)
  20680.  
  20681. -- add colval parameters
  20682. select @param_count = NULL
  20683. select @art_col = 1
  20684. select @spacer = N' '
  20685. select @cmd = ''
  20686.  
  20687. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  20688. select colid from syscolumns where id = @src_objid order by colid asc
  20689.  
  20690. OPEN hCColid
  20691.  
  20692. FETCH hCColid INTO @this_col
  20693.  
  20694. WHILE ( 1 = 1 )
  20695. begin
  20696.     if @@fetch_status = -1
  20697.     begin
  20698.         -- If called by sp_scriptxupdproc and it is the first time
  20699.         -- at the end of the cursor loop
  20700.         if @pkcolumns is null and @param_count is NULL
  20701.         begin
  20702.             -- Reset it so that we know we encountered cursor end once.
  20703.             select @param_count = 0
  20704.             -- Reopen cursor
  20705.             CLOSE hCColid
  20706.             OPEN hCColid
  20707.             FETCH hCColid INTO @this_col
  20708.             continue
  20709.         end
  20710.         else
  20711.             break;
  20712.     end
  20713.     exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  20714.     if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  20715.     begin
  20716.         exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  20717.         select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  20718.         select @art_col = @art_col + 1
  20719.         select @spacer = N','
  20720.  
  20721.         if len( @cmd ) > 3000
  20722.         begin
  20723.         insert into #proctext(procedure_text) values( @cmd )
  20724.             select @cmd = N''
  20725.         end
  20726.     end
  20727.     FETCH hCColid INTO @this_col
  20728. end
  20729. CLOSE hCColid
  20730. DEALLOCATE hCColid
  20731.  
  20732. select @param_count = @art_col -1
  20733.  
  20734. -- add pkval parameters
  20735. -- If it is null we are called by sp_scriptxupdproc, no need for PK params
  20736. if @pkcolumns is not null
  20737. begin
  20738.     select @art_col = 1
  20739.  
  20740.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  20741.     select colid from syscolumns where id = @src_objid order by colid asc
  20742.  
  20743.     OPEN hCColid
  20744.  
  20745.     FETCH hCColid INTO @this_col
  20746.  
  20747.     WHILE (@@fetch_status <> -1)
  20748.     begin
  20749.        exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  20750.        if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid )
  20751.        begin
  20752.             exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  20753.             select @cmd = @cmd + @spacer + N'@pkc' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  20754.             select @art_col = @art_col + 1
  20755.             select @spacer = N','
  20756.  
  20757.             if len( @cmd ) > 3000
  20758.             begin
  20759.             insert into #proctext(procedure_text) values( @cmd )
  20760.                 select @cmd = N''
  20761.             end
  20762.         end
  20763.         FETCH hCColid INTO @this_col
  20764.     end
  20765.     CLOSE hCColid
  20766.     DEALLOCATE hCColid
  20767. end
  20768.  
  20769. insert into #proctext(procedure_text) values ( @cmd )
  20770.  
  20771. go
  20772.  
  20773. EXEC dbo.sp_MS_marksystemobject sp_scriptupdateparams
  20774. GO
  20775.  
  20776.  
  20777. print ''
  20778. print 'Creating procedure sp_scriptreconwhereclause'
  20779. go
  20780.  
  20781. create procedure sp_scriptreconwhereclause @src_objid int, @pkcolumns binary(32), @artcolumns binary(32)
  20782. as
  20783. declare @this_col int
  20784. declare @art_col int
  20785. declare @spacer nvarchar(10)
  20786. declare @isset int
  20787. declare @cmd nvarchar(4000)
  20788.  
  20789. -- create WHERE clause
  20790.  
  20791. select @art_col = 1
  20792. select @spacer = N' '
  20793. select @cmd = N'where'
  20794.  
  20795. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  20796. select colid from syscolumns where id = @src_objid order by colid asc
  20797.  
  20798. OPEN hCColid
  20799.  
  20800. FETCH hCColid INTO @this_col
  20801.  
  20802. WHILE (@@fetch_status <> -1)
  20803. begin
  20804.     exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  20805.     if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid )
  20806.     begin
  20807.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  20808.         if @isset != 0 
  20809.         begin
  20810.             select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = @c' + convert( nvarchar, @art_col ) 
  20811.             select @spacer = N' and '
  20812.  
  20813.             if len( @cmd ) > 3000
  20814.             begin
  20815.                 insert into #proctext(procedure_text) values( @cmd )
  20816.                 select @cmd = N''
  20817.             end
  20818.         end
  20819.         select @art_col = @art_col + 1
  20820.     end
  20821.     FETCH hCColid INTO @this_col
  20822. end
  20823. CLOSE hCColid
  20824. DEALLOCATE hCColid
  20825.  
  20826. insert into #proctext(procedure_text) values( @cmd )
  20827.  
  20828. go
  20829.  
  20830. EXEC dbo.sp_MS_marksystemobject sp_scriptreconwhereclause
  20831. GO
  20832.  
  20833.  
  20834.  
  20835.  
  20836. --------------------------------------------------------------------
  20837. --------------------------------------------------------------------
  20838.  
  20839. print ''
  20840. print 'Creating procedure sp_script_reconciliation_insproc'
  20841. go
  20842.  
  20843. create procedure sp_script_reconciliation_insproc (
  20844.     @artid int)
  20845. as
  20846. BEGIN
  20847. declare @cmd          nvarchar(4000)
  20848. declare @dest_owner   nvarchar(255)
  20849. declare @dest_tabname sysname
  20850. declare @src_objid    int
  20851. declare @artcolumns   binary(32)
  20852. declare @pkcolumns    binary(32)
  20853. declare @ins_cmd      nvarchar(255)
  20854. declare @dest_proc    sysname
  20855. declare @this_col     int
  20856. declare @art_col      int
  20857. declare @isset        int
  20858.  
  20859. declare @typestring   nvarchar(255)
  20860. declare @spacer       nvarchar(1)
  20861.     , @identity_insert bit
  20862.     
  20863.  
  20864. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  20865. begin
  20866.     raiserror (14155, 16, 1 )
  20867.     return 1
  20868. end
  20869.  
  20870. -------- create temp table for command fragments
  20871.  
  20872. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  20873.  
  20874. -------- get sysarticles information
  20875.  
  20876. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  20877.        @src_objid = objid, @artcolumns = columns, @ins_cmd = ins_cmd
  20878. from sysarticles
  20879. where artid = @artid
  20880.  
  20881. if @dest_owner is not null
  20882. begin
  20883.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  20884. end
  20885. else
  20886. begin
  20887.     select @dest_owner = N''
  20888. end
  20889.  
  20890. -- Check to see if identity insert must be turned on
  20891. -- i.e. Does the table has identity that are included in the partition?
  20892. exec sp_MSis_identity_insert null, null, @identity_insert output, @artid
  20893. --
  20894.  
  20895. -------- get dest proc name
  20896.  
  20897. if( 1 != charindex( N'CALL', upper(@ins_cmd collate SQL_Latin1_General_CP1_CS_AS) ) ) or @ins_cmd is null
  20898. begin
  20899.     raiserror (14156, 16, 1 )
  20900.     return 1
  20901. end
  20902.  
  20903. select @dest_proc = substring( @ins_cmd, 6, len( @ins_cmd ) - 4 )
  20904. select @cmd = N'create procedure ' + QUOTENAME(@dest_proc) + N';2'
  20905.  
  20906. -------- construct parameter list
  20907.  
  20908.  
  20909. select @art_col = 1
  20910. select @spacer = N' '
  20911.  
  20912. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  20913. select colid from syscolumns where id = @src_objid order by colid asc
  20914.  
  20915. OPEN hCColid
  20916.  
  20917. FETCH hCColid INTO @this_col
  20918.  
  20919. WHILE (@@fetch_status <> -1)
  20920. begin
  20921.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  20922.    if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  20923.    begin
  20924.         if len( @cmd ) > 3000
  20925.         begin
  20926.         insert into #proctext(procedure_text) values( @cmd )
  20927.             select @cmd = N''
  20928.         end
  20929.  
  20930.         exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  20931.         select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  20932.         select @art_col = @art_col + 1
  20933.         select @spacer = N','
  20934.    end
  20935.    FETCH hCColid INTO @this_col
  20936. end
  20937. CLOSE hCColid
  20938. DEALLOCATE hCColid
  20939.  
  20940.  
  20941. -- save off cmd fragment
  20942.  
  20943. insert into #proctext(procedure_text) values( @cmd )
  20944.  
  20945. insert into #proctext(procedure_text) values( N'as' )
  20946.  
  20947. ------- construct proc body
  20948.  
  20949. ---- if already exists, apply as update
  20950.  
  20951. insert into #proctext(procedure_text) 
  20952.     values( N'if exists ( select * from ' + @dest_owner + QUOTENAME(@dest_tabname) )
  20953. exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  20954. exec dbo.sp_scriptreconwhereclause @src_objid, @pkcolumns, @artcolumns
  20955. insert into #proctext(procedure_text) values( N')' )
  20956. insert into #proctext(procedure_text) values (N'begin')
  20957.  
  20958.  
  20959. if( @artcolumns != @pkcolumns )
  20960. begin
  20961.     -- construct update 
  20962.  
  20963.     select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set'
  20964.  
  20965.     -- create SET clause
  20966.  
  20967.     select @art_col = 1
  20968.     select @spacer = N' '
  20969.  
  20970.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  20971.     select colid from syscolumns where id = @src_objid order by colid asc
  20972.  
  20973.     OPEN hCColid
  20974.  
  20975.     FETCH hCColid INTO @this_col
  20976.  
  20977.     WHILE (@@fetch_status <> -1)
  20978.     begin
  20979.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  20980.         if @isset != 0  and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  20981.         begin
  20982.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  20983.             if @isset = 0
  20984.             begin
  20985.                 if not (@identity_insert = 1 and 
  20986.                     columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  20987.                 begin
  20988.                     select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = @c' + convert( nvarchar, @art_col ) 
  20989.                     select @spacer = N','
  20990.  
  20991.                     if len( @cmd ) > 3000
  20992.                     begin
  20993.                         insert into #proctext(procedure_text) values( @cmd )
  20994.                         select @cmd = N''
  20995.                     end
  20996.                 end
  20997.             end
  20998.             select @art_col = @art_col + 1
  20999.         end
  21000.         FETCH hCColid INTO @this_col
  21001.        end
  21002.     CLOSE hCColid
  21003.     DEALLOCATE hCColid
  21004.  
  21005.     insert into #proctext(procedure_text) values( @cmd )
  21006.  
  21007.     exec dbo.sp_scriptreconwhereclause @src_objid, @pkcolumns, @artcolumns
  21008. end
  21009.  
  21010. -- all article columns are included in the PK, & PK already exists, do nothing
  21011. else 
  21012. begin
  21013.     insert into #proctext(procedure_text ) values( N'return' )
  21014. end
  21015.  
  21016.  
  21017. insert into #proctext(procedure_text) values (N'end')
  21018. insert into #proctext(procedure_text) values (N'else')
  21019. insert into #proctext(procedure_text) values (N'begin')
  21020.  
  21021. ---- normal insert
  21022.  
  21023. -- set identity_insert on
  21024. if @identity_insert = 1
  21025. begin
  21026.     select @cmd = N'
  21027. set identity_insert ' + @dest_owner + QUOTENAME(@dest_tabname) + ' on'
  21028.     insert into #proctext(procedure_text) values( @cmd )
  21029. end
  21030.  
  21031. -- prepare the column list
  21032.  
  21033. select @cmd = N'insert into ' + @dest_owner + QUOTENAME(@dest_tabname) + N' ('
  21034. select @art_col = 1
  21035. select @spacer = N' '
  21036.  
  21037. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  21038. select colid from syscolumns where id = @src_objid order by colid asc
  21039.  
  21040. OPEN hCColid
  21041.  
  21042. FETCH hCColid INTO @this_col
  21043.  
  21044. WHILE (@@fetch_status <> -1)
  21045. begin
  21046.     exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  21047.     if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  21048.     begin
  21049.         if len( @cmd ) > 3000
  21050.         begin
  21051.         insert into #proctext(procedure_text) values( @cmd )
  21052.             select @cmd = N''
  21053.         end
  21054.  
  21055.         select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col))  
  21056.         select @art_col = @art_col + 1
  21057.         select @spacer = N','
  21058.     end
  21059.     FETCH hCColid INTO @this_col
  21060. end
  21061. CLOSE hCColid
  21062. DEALLOCATE hCColid
  21063.  
  21064. -- now the data parameter list
  21065.  
  21066. select @cmd = @cmd + N' ) values ('
  21067. select @art_col = 1
  21068. select @spacer = N' '
  21069.  
  21070. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  21071. select colid from syscolumns where id = @src_objid order by colid asc
  21072.  
  21073. OPEN hCColid
  21074.  
  21075. FETCH hCColid INTO @this_col
  21076.  
  21077. WHILE (@@fetch_status <> -1)
  21078. begin
  21079.     exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  21080.     if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  21081.     begin
  21082.         if len( @cmd ) > 3000
  21083.         begin
  21084.         insert into #proctext(procedure_text) values( @cmd )
  21085.             select @cmd = N''
  21086.         end
  21087.  
  21088.         select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) 
  21089.         select @art_col = @art_col + 1
  21090.         select @spacer = N','
  21091.     end
  21092.     FETCH hCColid INTO @this_col
  21093. end
  21094. CLOSE hCColid
  21095. DEALLOCATE hCColid
  21096.  
  21097. -- finish up proc body
  21098.  
  21099. select @cmd = @cmd + N' )'
  21100.  
  21101. -- save off cmd fragement
  21102.  
  21103. insert into #proctext(procedure_text) values( @cmd )
  21104.  
  21105. -- set identity_insert off
  21106. if @identity_insert = 1
  21107. begin
  21108.     select @cmd = N'
  21109. set identity_insert ' + @dest_owner + QUOTENAME(@dest_tabname) + ' off'
  21110.     insert into #proctext(procedure_text) values( @cmd )
  21111. end
  21112.  
  21113. insert into #proctext(procedure_text) values (N'end')
  21114.  
  21115. -- send fragments to client
  21116.  
  21117. select procedure_text from #proctext order by c1 asc
  21118. END
  21119. go
  21120.  
  21121. EXEC dbo.sp_MS_marksystemobject sp_script_reconciliation_insproc
  21122. GO
  21123.  
  21124.  
  21125. --------------------------------------------------------------------
  21126. --------------------------------------------------------------------
  21127.  
  21128. print ''
  21129. print 'Creating procedure sp_script_reconciliation_delproc'
  21130. go
  21131.  
  21132. create procedure sp_script_reconciliation_delproc @artid int
  21133. as
  21134. declare @cmd          nvarchar(4000)
  21135. declare @dest_owner   nvarchar(255)
  21136. declare @dest_tabname sysname
  21137. declare @src_objid    int
  21138. declare @pkcolumns    binary(32)
  21139. declare @del_cmd      nvarchar(255)
  21140. declare @dest_proc    sysname
  21141. declare @this_col     int
  21142. declare @art_col      int
  21143. declare @isset        int
  21144.  
  21145. declare @typestring   nvarchar(255)
  21146. declare @spacer       nvarchar(10)
  21147.  
  21148. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  21149. begin
  21150.     raiserror (14155, 16, 1 )
  21151.     return 1
  21152. end
  21153.  
  21154. -------- create temp table for command fragments
  21155.  
  21156. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  21157.  
  21158. -- get sysarticles information
  21159.  
  21160. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  21161.        @src_objid = objid, @del_cmd = del_cmd
  21162. from sysarticles
  21163. where artid = @artid
  21164.  
  21165. if @dest_owner is not null
  21166. begin
  21167.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  21168. end
  21169. else
  21170. begin
  21171.     select @dest_owner = N''
  21172. end
  21173.  
  21174. -------- get dest proc name
  21175.  
  21176. if( 1 != charindex( N'CALL', upper(@del_cmd collate SQL_Latin1_General_CP1_CS_AS) ) ) or @del_cmd is null
  21177. begin
  21178.     raiserror (14156, 16, 1 )
  21179.     return 1
  21180. end
  21181.  
  21182. select @dest_proc = substring( @del_cmd, 6, len( @del_cmd ) - 4 )
  21183. select @cmd = N'create procedure ' + QUOTENAME(@dest_proc) + N';2'
  21184.  
  21185.  
  21186. -------- construct parameter list
  21187.  
  21188.  
  21189. select @art_col = 1
  21190. select @spacer = N' '
  21191.  
  21192. exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  21193.  
  21194. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  21195. select colid from syscolumns where id = @src_objid order by colid asc
  21196.  
  21197. OPEN hCColid
  21198.  
  21199. FETCH hCColid INTO @this_col
  21200.  
  21201. WHILE (@@fetch_status <> -1)
  21202. begin
  21203.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  21204.    if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid )
  21205.    begin
  21206.         if len( @cmd ) > 3000
  21207.         begin
  21208.         insert into #proctext(procedure_text) values( @cmd )
  21209.             select @cmd = N''
  21210.         end
  21211.  
  21212.         exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  21213.         select @cmd = @cmd + @spacer + N'@pkc' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  21214.         select @art_col = @art_col + 1
  21215.         select @spacer = N','
  21216.    end
  21217.     FETCH hCColid INTO @this_col
  21218. end
  21219.  
  21220. CLOSE hCColid
  21221. DEALLOCATE hCColid
  21222.  
  21223. -- save off 
  21224.  
  21225. insert into #proctext(procedure_text) values( @cmd )
  21226. insert into #proctext(procedure_text) values( N'as' )
  21227.  
  21228. ------- construct proc body
  21229.  
  21230. insert into #proctext(procedure_text) values( N'delete ' + @dest_owner + QUOTENAME(@dest_tabname) ) 
  21231.  
  21232. exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns
  21233.  
  21234. -- flush to client
  21235.  
  21236. select procedure_text from #proctext order by c1 asc
  21237.  
  21238.  
  21239. go
  21240.  
  21241. EXEC dbo.sp_MS_marksystemobject sp_script_reconciliation_delproc
  21242. GO
  21243.  
  21244. --------------------------------------------------------------------
  21245. --------------------------------------------------------------------
  21246.  
  21247. print ''
  21248. print 'Creating procedure sp_script_reconciliation_xdelproc'
  21249. go
  21250.  
  21251. create procedure sp_script_reconciliation_xdelproc @artid int
  21252. as
  21253. declare @cmd          nvarchar(4000)
  21254. declare @dest_owner   nvarchar(255)
  21255. declare @dest_tabname sysname
  21256. declare @src_objid    int
  21257. declare @columns    binary(32)
  21258. declare @pkcolumns    binary(32)
  21259. declare @del_cmd      nvarchar(255)
  21260. declare @dest_proc    sysname
  21261. declare @this_col     int
  21262. declare @art_col      int
  21263. declare @isset        int
  21264.  
  21265. declare @typestring   nvarchar(255)
  21266. declare @spacer       nvarchar(10)
  21267.  
  21268. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  21269. begin
  21270.     raiserror (14155, 16, 1 )
  21271.     return 1
  21272. end
  21273.  
  21274. -------- create temp table for command fragments
  21275.  
  21276. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  21277.  
  21278. -- get sysarticles information
  21279.  
  21280. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  21281.        @src_objid = objid, @del_cmd = del_cmd, @columns = columns
  21282. from sysarticles
  21283. where artid = @artid
  21284.  
  21285. if @dest_owner is not null
  21286. begin
  21287.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  21288. end
  21289. else
  21290. begin
  21291.     select @dest_owner = N''
  21292. end
  21293.  
  21294. -------- get dest proc name
  21295.  
  21296. if( 1 != charindex( N'XCALL', upper(@del_cmd collate SQL_Latin1_General_CP1_CS_AS) ) ) or @del_cmd is null
  21297. begin
  21298.     raiserror (14156, 16, 1 )
  21299.     return 1
  21300. end
  21301.  
  21302. select @dest_proc = substring( @del_cmd, 7, len( @del_cmd ) - 5 )
  21303. select @cmd = N'create procedure ' + QUOTENAME(@dest_proc) + N';2'
  21304.  
  21305. -------- construct parameter list
  21306.  
  21307.  
  21308. select @art_col = 1
  21309. select @spacer = N' '
  21310.  
  21311. exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  21312.  
  21313. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  21314. select colid from syscolumns where id = @src_objid order by colid asc
  21315.  
  21316. OPEN hCColid
  21317.  
  21318. FETCH hCColid INTO @this_col
  21319.  
  21320. WHILE (@@fetch_status <> -1)
  21321. begin
  21322.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  21323.    if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  21324.    begin
  21325.         if len( @cmd ) > 3000
  21326.         begin
  21327.         insert into #proctext(procedure_text) values( @cmd )
  21328.             select @cmd = N''
  21329.         end
  21330.  
  21331.         exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  21332.         select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  21333.         select @art_col = @art_col + 1
  21334.         select @spacer = N','
  21335.    end
  21336.    FETCH hCColid INTO @this_col
  21337. end
  21338.  
  21339. CLOSE hCColid
  21340. DEALLOCATE hCColid
  21341.  
  21342. -- save off 
  21343.  
  21344. insert into #proctext(procedure_text) values( @cmd )
  21345. insert into #proctext(procedure_text) values( N'as' )
  21346.  
  21347. ------- construct proc body
  21348.  
  21349. insert into #proctext(procedure_text) values( N'delete ' + @dest_owner + QUOTENAME(@dest_tabname) ) 
  21350.  
  21351. exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns, N'@c', @columns
  21352.  
  21353. -- flush to client
  21354.  
  21355. select procedure_text from #proctext order by c1 asc
  21356.  
  21357.  
  21358.  
  21359.  
  21360. go
  21361.  
  21362. EXEC dbo.sp_MS_marksystemobject sp_script_reconciliation_xdelproc
  21363. GO
  21364.  
  21365.  
  21366. --------------------------------------------------------------------
  21367. --------------------------------------------------------------------
  21368.  
  21369. print ''
  21370. print 'Creating procedure sp_scriptinsproc'
  21371. go
  21372.  
  21373. create procedure sp_scriptinsproc (
  21374.     @artid int)
  21375. as
  21376. BEGIN
  21377. declare @cmd          nvarchar(4000)
  21378.         ,@dest_owner   nvarchar(255)
  21379.         ,@dest_tabname sysname
  21380.         ,@src_objid    int
  21381.         ,@columns      binary(32)
  21382.         ,@ins_cmd      nvarchar(255)
  21383.         ,@dest_proc    sysname
  21384.         ,@this_col     int
  21385.         ,@art_col      int
  21386.         ,@isset        int
  21387.         ,@pubid          int
  21388.  
  21389.         ,@identity_insert bit
  21390.         ,@rc int
  21391.         ,@colname sysname
  21392.         ,@ccoltype     sysname
  21393.         ,@typestring   nvarchar(255)
  21394.         ,@spacer       nvarchar(1)
  21395.         ,@queued_check bit
  21396.         ,@column_string nvarchar(4000)
  21397.         ,@var_string nvarchar(4000)
  21398.         ,@qwhere_string nvarchar(4000)
  21399.         ,@indkey      int
  21400.         ,@indid       int
  21401.  
  21402. set nocount on
  21403.  
  21404. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  21405. begin
  21406.     raiserror (14155, 16, 1 )
  21407.     return 1
  21408. end
  21409.  
  21410. -------- create temp table for command fragments and insert column list
  21411.  
  21412. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  21413. create table #collisttab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  21414.  
  21415. -------- get sysarticles information
  21416.  
  21417. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  21418.        @src_objid = objid, @columns = columns, @ins_cmd = ins_cmd,
  21419.        @pubid = pubid
  21420. from sysarticles
  21421. where artid = @artid
  21422.  
  21423. -- Check to see if identity insert must be turned on
  21424. -- i.e. Does the table has identity that are included in the partition?
  21425. exec sp_MSis_identity_insert null, null, @identity_insert output, @artid
  21426. --
  21427.  
  21428. if @dest_owner is not null
  21429. begin
  21430.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  21431. end
  21432. else
  21433. begin
  21434.     select @dest_owner = N''
  21435. end
  21436.  
  21437. -- Check if this is a queued publication
  21438. select @queued_check = ISNULL(allow_queued_tran, 0) 
  21439. from syspublications
  21440. where pubid = @pubid
  21441.  
  21442. -------- get dest proc name
  21443.  
  21444. if( 1 != charindex( N'CALL', upper(@ins_cmd collate SQL_Latin1_General_CP1_CS_AS) ) ) or @ins_cmd is null
  21445. begin
  21446.     raiserror (14156, 16, 1 )
  21447.     return 1
  21448. end
  21449.  
  21450. select @dest_proc = substring( @ins_cmd, 6, len( @ins_cmd ) - 4 )
  21451. select @cmd = N'if exists (select * from sysobjects where type = ''P'' and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  21452. insert into #proctext(procedure_text) values( @cmd )
  21453. insert into #proctext(procedure_text) values( N'go' )
  21454. select @cmd = N'create procedure ' + QUOTENAME(@dest_proc)
  21455.  
  21456. -------- construct parameter list
  21457.  
  21458.  
  21459. select @art_col = 1
  21460. select @spacer = N' '
  21461.  
  21462. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  21463. select colid from syscolumns where id = @src_objid order by colid asc
  21464.  
  21465. OPEN hCColid
  21466.  
  21467. FETCH hCColid INTO @this_col
  21468.  
  21469. WHILE (@@fetch_status <> -1)
  21470. begin
  21471.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  21472.    if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  21473.    begin
  21474.         if len( @cmd ) > 3000
  21475.         begin
  21476.         insert into #proctext(procedure_text) values( @cmd )
  21477.             select @cmd = N''
  21478.         end
  21479.  
  21480.         exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  21481.         select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  21482.         select @art_col = @art_col + 1
  21483.         select @spacer = N','
  21484.    end
  21485.    FETCH hCColid INTO @this_col
  21486. end
  21487.  
  21488. CLOSE hCColid
  21489. DEALLOCATE hCColid
  21490.  
  21491. -- save off cmd fragment
  21492.  
  21493. insert into #proctext(procedure_text) values( @cmd )
  21494.  
  21495. select @cmd = N'
  21496. AS
  21497. BEGIN
  21498. '
  21499. insert into #proctext(procedure_text) values( @cmd )
  21500.  
  21501. ------- construct proc body
  21502.  
  21503. -- For Queued case, build a temp table of index columns
  21504. -- we also need temp tables for where clause list
  21505. if (@queued_check = 1)
  21506. begin
  21507.     declare @source_object nvarchar(540)
  21508.  
  21509.     --
  21510.     -- Get the object owner name and build a owner qualified 
  21511.     -- source object name
  21512.     --
  21513.     select @source_object = QUOTENAME(u.name) 
  21514.     from sysusers u, sysobjects o 
  21515.     where o.id = @src_objid and o.uid = u.uid
  21516.  
  21517.     select @source_object = @source_object + N'.' + QUOTENAME(OBJECT_NAME(@src_objid))
  21518.  
  21519.     create table #wherecltab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)    
  21520.     create table #indcoltab ( colname sysname collate database_default )
  21521.     
  21522.     exec @indid = dbo.sp_MStable_has_unique_index @src_objid
  21523.     select @indkey = 1;    
  21524.     while (@indkey <= 16)
  21525.     begin
  21526.         select @colname = index_col(@source_object, @indid, @indkey)
  21527.         if (@colname is NULL) 
  21528.             select @indkey = 16
  21529.         else
  21530.             insert into #indcoltab(colname) values(@colname)
  21531.  
  21532.         select @indkey = @indkey + 1
  21533.     end
  21534. end
  21535.  
  21536. -- Generate strings for col names and variables
  21537. select @art_col = 0
  21538. select @spacer = N' '
  21539.  
  21540. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  21541. select colid from syscolumns where id = @src_objid order by colid asc
  21542.  
  21543. OPEN hCColid
  21544.  
  21545. FETCH hCColid INTO @this_col
  21546.  
  21547. WHILE (@@fetch_status <> -1)
  21548. begin
  21549.     exec @rc = dbo.sp_MSget_colinfo @src_objid, @this_col, @columns, 1, @colname output, @ccoltype output
  21550.     if @rc = 0  and EXISTS (select name from syscolumns where id=@src_objid and colid=@this_col and iscomputed<>1)
  21551.     begin
  21552.         select @art_col = @art_col + 1
  21553.         if (@art_col = 1)
  21554.         begin
  21555.             select @column_string = QUOTENAME(@colname)
  21556.             select @var_string = N'@c' + cast(@art_col as nvarchar(4))
  21557.         end
  21558.         else
  21559.         begin
  21560.             select @column_string = @column_string + N', ' + QUOTENAME(@colname)
  21561.             select @var_string = @var_string + N', @c' + cast(@art_col as nvarchar(4))
  21562.         end
  21563.  
  21564.         -- transfer column list string to table if too large
  21565.         if (len(@column_string) > 3000)
  21566.         begin
  21567.             insert into #collisttab(procedure_text) values( @column_string )
  21568.             select @column_string = ' '
  21569.         end
  21570.  
  21571.         -- queued processing : add to where clause if column part of PK
  21572.         if (@queued_check = 1)
  21573.         begin
  21574.             if (@colname in (select colname from #indcoltab))
  21575.             begin
  21576.                 select @qwhere_string = case 
  21577.                     when (@qwhere_string IS NULL) then 
  21578.                         QUOTENAME(@colname) + N'=@c' + cast(@art_col as nvarchar(4))
  21579.                     else
  21580.                         @qwhere_string + N' and ' + QUOTENAME(@colname) + N'=@c' + cast(@art_col as nvarchar(4))
  21581.                     end
  21582.  
  21583.                 -- transfer where clause string to table if too large
  21584.                 if (len(@qwhere_string) > 3000)
  21585.                 begin
  21586.                     insert into #wherecltab(procedure_text) values( @qwhere_string )
  21587.                     select @qwhere_string = ' '
  21588.                 end
  21589.             end
  21590.         end
  21591.     end
  21592.     FETCH hCColid INTO @this_col
  21593. end
  21594.  
  21595. CLOSE hCColid
  21596. DEALLOCATE hCColid
  21597.  
  21598. -- insert the remaining strings for column list and where clause
  21599. insert into #collisttab(procedure_text) values( @column_string )
  21600. if (@queued_check = 1)
  21601.     insert into #wherecltab(procedure_text) values( @qwhere_string )
  21602.  
  21603. --
  21604. -- If we are a part of queued publication then 
  21605. -- insert only if PK does not exist
  21606. --
  21607. if (@queued_check = 1)
  21608. begin
  21609.     select @cmd = N'
  21610.     if not exists (select * from ' + @dest_owner + QUOTENAME(@dest_tabname) + N' 
  21611.         where '
  21612.     insert into #proctext(procedure_text) values( @cmd )
  21613.     insert into #proctext(procedure_text) 
  21614.         select procedure_text from #wherecltab order by c1 asc
  21615.     select @cmd = N')
  21616.     BEGIN'
  21617.     insert into #proctext(procedure_text) values( @cmd )
  21618.     drop table #wherecltab
  21619.     drop table #indcoltab
  21620. end
  21621.  
  21622.  
  21623. -- set identity_insert on
  21624. if @identity_insert = 1
  21625. begin
  21626.     select @cmd = N'
  21627.     set identity_insert ' + @dest_owner + QUOTENAME(@dest_tabname) + ' on'
  21628.     insert into #proctext(procedure_text) values( @cmd )
  21629. end
  21630.  
  21631.  
  21632. --
  21633. -- prepare the insert statement now
  21634. --
  21635. select @cmd = N'
  21636. insert into ' +  @dest_owner + QUOTENAME(@dest_tabname)  + N'( '
  21637. insert into #proctext(procedure_text) values( @cmd )
  21638. insert into #proctext(procedure_text) 
  21639.     select procedure_text from #collisttab order by c1 asc
  21640. select @cmd = N' )'
  21641. insert into #proctext(procedure_text) values( @cmd )
  21642. if @art_col > 0
  21643. begin
  21644.     select @cmd = N'
  21645. values ( '
  21646.     insert into #proctext(procedure_text) values( @cmd )
  21647.     insert into #proctext(procedure_text) values( @var_string )
  21648.     select @cmd = N' )
  21649. '
  21650.     insert into #proctext(procedure_text) values( @cmd )
  21651. end
  21652.  
  21653. -- set identity_insert off
  21654. if @identity_insert = 1
  21655. begin
  21656.     select @cmd = N'
  21657.     set identity_insert ' + @dest_owner + QUOTENAME(@dest_tabname) + ' off'
  21658.     insert into #proctext(procedure_text) values( @cmd )
  21659. end
  21660.  
  21661. --
  21662. -- If we are a part of queued publication then 
  21663. -- add the block delimiter
  21664. --
  21665. drop table #collisttab
  21666. if (@queued_check = 1)
  21667. begin
  21668.     select @cmd = N'
  21669.     END
  21670. END'
  21671. end
  21672. else
  21673.     select @cmd = N'
  21674. END'
  21675. insert into #proctext(procedure_text) values( @cmd )
  21676.  
  21677. -- send fragements to client
  21678.  
  21679. select procedure_text from #proctext order by c1 asc
  21680. END
  21681. go
  21682.  
  21683. EXEC dbo.sp_MS_marksystemobject sp_scriptinsproc
  21684. GO
  21685.  
  21686. ----------------------------------------------------
  21687. ---------------------------------------------------
  21688. print ''
  21689. print 'Creating procedure sp_scriptdelproc'
  21690. go
  21691.  
  21692. create procedure sp_scriptdelproc @artid int
  21693. as
  21694. declare @cmd          nvarchar(4000)
  21695. declare @dest_owner   nvarchar(255)
  21696. declare @dest_tabname sysname
  21697. declare @src_objid    int
  21698. declare @pkcolumns    binary(32)
  21699. declare @del_cmd      nvarchar(255)
  21700. declare @dest_proc    sysname
  21701. declare @this_col     int
  21702. declare @art_col      int
  21703. declare @isset        int, @pubid int
  21704.  
  21705. declare @typestring   nvarchar(255)
  21706. declare @spacer       nvarchar(10)
  21707.  
  21708. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  21709. begin
  21710.     raiserror (14155, 16, 1 )
  21711.     return 1
  21712. end
  21713.  
  21714. -------- create temp table for command fragments
  21715.  
  21716. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  21717.  
  21718. -- get sysarticles information
  21719.  
  21720. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  21721.        @src_objid = objid, @del_cmd = del_cmd, @pubid = pubid
  21722. from sysarticles
  21723. where artid = @artid
  21724.  
  21725. if @dest_owner is not null
  21726. begin
  21727.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  21728. end
  21729. else
  21730. begin
  21731.     select @dest_owner = N''
  21732. end
  21733.  
  21734. -------- get dest proc name
  21735.  
  21736. if( 1 != charindex( N'CALL', upper(@del_cmd collate SQL_Latin1_General_CP1_CS_AS) ) ) or @del_cmd is null
  21737. begin
  21738.     raiserror (14156, 16, 1 )
  21739.     return 1
  21740. end
  21741.  
  21742. select @dest_proc = substring( @del_cmd, 6, len( @del_cmd ) - 4 )
  21743. select @cmd = N'if exists (select * from sysobjects where type = ''P'' and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  21744. insert into #proctext(procedure_text) values( @cmd )
  21745. insert into #proctext(procedure_text) values( N'go' )
  21746. select @cmd = N'create procedure ' + QUOTENAME(@dest_proc)
  21747.  
  21748. -------- construct parameter list
  21749.  
  21750.  
  21751. select @art_col = 1
  21752. select @spacer = N' '
  21753.  
  21754. exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  21755.  
  21756. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  21757. select colid from syscolumns where id = @src_objid order by colid asc
  21758.  
  21759. OPEN hCColid
  21760.  
  21761. FETCH hCColid INTO @this_col
  21762.  
  21763. WHILE (@@fetch_status <> -1)
  21764. begin
  21765.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  21766.    if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid )
  21767.    begin
  21768.         if len( @cmd ) > 3000
  21769.         begin
  21770.         insert into #proctext(procedure_text) values( @cmd )
  21771.             select @cmd = N''
  21772.         end
  21773.  
  21774.         exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  21775.         select @cmd = @cmd + @spacer + N'@pkc' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  21776.         select @art_col = @art_col + 1
  21777.         select @spacer = N','
  21778.    end
  21779.     FETCH hCColid INTO @this_col
  21780. end
  21781.  
  21782. CLOSE hCColid
  21783. DEALLOCATE hCColid
  21784.  
  21785. -- save off 
  21786.  
  21787. insert into #proctext(procedure_text) values( @cmd )
  21788. insert into #proctext(procedure_text) values( N'as' )
  21789.  
  21790. ------- construct proc body
  21791.  
  21792. insert into #proctext(procedure_text) values( N'delete ' + @dest_owner + QUOTENAME(@dest_tabname) ) 
  21793.  
  21794. exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns
  21795.  
  21796. if exists (select * from syspublications where pubid = @pubid and allow_queued_tran = 0)
  21797.     exec dbo.sp_MSscript_missing_row_check
  21798. -- flush to client
  21799.  
  21800. select procedure_text from #proctext order by c1 asc
  21801.  
  21802.  
  21803. go
  21804.  
  21805. EXEC dbo.sp_MS_marksystemobject sp_scriptdelproc
  21806. GO
  21807.  
  21808. ----------------------------------------------------
  21809. ---------------------------------------------------
  21810. print ''
  21811. print 'Creating procedure sp_scriptxdelproc'
  21812. go
  21813.  
  21814. create procedure sp_scriptxdelproc @artid int
  21815. as
  21816. declare @cmd          nvarchar(4000)
  21817. declare @dest_owner   nvarchar(255)
  21818. declare @dest_tabname sysname
  21819. declare @src_objid    int
  21820. declare @columns    binary(32)
  21821. declare @pkcolumns    binary(32)
  21822. declare @del_cmd      nvarchar(255)
  21823. declare @dest_proc    sysname
  21824. declare @this_col     int
  21825. declare @art_col      int
  21826. declare @isset        int
  21827. declare @pubid          int
  21828. declare @typestring   nvarchar(255)
  21829. declare @spacer       nvarchar(10)
  21830. declare @queued_check bit
  21831.         ,@qwhere_string nvarchar(4000)
  21832.  
  21833. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  21834. begin
  21835.     raiserror (14155, 16, 1 )
  21836.     return 1
  21837. end
  21838.  
  21839. -------- create temp table for command fragments
  21840.  
  21841. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  21842.  
  21843. -- get sysarticles information
  21844.  
  21845. select @pubid = pubid, @dest_owner = dest_owner, @dest_tabname = dest_table, 
  21846.        @src_objid = objid, @del_cmd = del_cmd, @columns = columns
  21847. from sysarticles
  21848. where artid = @artid
  21849.  
  21850. if @dest_owner is not null
  21851. begin
  21852.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  21853. end
  21854. else
  21855. begin
  21856.     select @dest_owner = N''
  21857. end
  21858.  
  21859. -- Check if this is a queued publication
  21860. select @queued_check = ISNULL(allow_queued_tran, 0) 
  21861. from syspublications
  21862. where pubid = @pubid
  21863.  
  21864. -------- get dest proc name
  21865.  
  21866. if( 1 != charindex( N'XCALL', upper(@del_cmd collate SQL_Latin1_General_CP1_CS_AS) ) ) or @del_cmd is null
  21867. begin
  21868.     raiserror (14156, 16, 1 )
  21869.     return 1
  21870. end
  21871.  
  21872. select @dest_proc = substring( @del_cmd, 7, len( @del_cmd ) - 5 )
  21873. select @cmd = N'if exists (select * from sysobjects where type = ''P'' and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  21874. insert into #proctext(procedure_text) values( @cmd )
  21875. insert into #proctext(procedure_text) values( N'go' )
  21876. select @cmd = N'create procedure ' + QUOTENAME(@dest_proc)
  21877.  
  21878. -------- construct parameter list
  21879.  
  21880.  
  21881. select @art_col = 1
  21882. select @spacer = N' '
  21883.  
  21884. exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  21885.  
  21886. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  21887. select colid from syscolumns where id = @src_objid order by colid asc
  21888.  
  21889. OPEN hCColid
  21890.  
  21891. FETCH hCColid INTO @this_col
  21892.  
  21893. WHILE (@@fetch_status <> -1)
  21894. begin
  21895.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  21896.    if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  21897.    begin
  21898.         if len( @cmd ) > 3000
  21899.         begin
  21900.         insert into #proctext(procedure_text) values( @cmd )
  21901.             select @cmd = N''
  21902.         end
  21903.  
  21904.         exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  21905.         select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  21906.  
  21907.         --
  21908.         -- Queued processing:if this is the row version column : need to add to where clause
  21909.         --
  21910.         if ((@queued_check = 1) and (col_name( @src_objid, @this_col) = N'msrepl_tran_version'))
  21911.             select @qwhere_string = N' and msrepl_tran_version = @c' + convert( nvarchar, @art_col )
  21912.  
  21913.         select @art_col = @art_col + 1
  21914.         select @spacer = N','
  21915.    end
  21916.    FETCH hCColid INTO @this_col
  21917. end
  21918.  
  21919. CLOSE hCColid
  21920. DEALLOCATE hCColid
  21921.  
  21922. -- save off 
  21923.  
  21924. insert into #proctext(procedure_text) values( @cmd )
  21925. insert into #proctext(procedure_text) values( N'as' )
  21926.  
  21927. ------- construct proc body
  21928.  
  21929. insert into #proctext(procedure_text) values( N'delete ' + @dest_owner + QUOTENAME(@dest_tabname) ) 
  21930.  
  21931. exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns, N'@c', @columns
  21932. if (@queued_check = 1)
  21933.     insert into #proctext(procedure_text) values( @qwhere_string )
  21934. else
  21935.     exec dbo.sp_MSscript_missing_row_check
  21936.  
  21937. -- flush to client
  21938.  
  21939. select procedure_text from #proctext order by c1 asc
  21940.  
  21941.  
  21942. go
  21943.  
  21944. EXEC dbo.sp_MS_marksystemobject sp_scriptxdelproc
  21945. GO
  21946.  
  21947. ----------------------------------------------------------------------------------------------
  21948. ----------------------------------------------------------------------------------------------
  21949. ----------------------------------------------------------------------------------------------
  21950.  
  21951. print ''
  21952. print 'Creating procedure sp_scriptupdproc'
  21953. go
  21954.  
  21955. create procedure sp_scriptupdproc @artid int
  21956. as
  21957. declare @cmd          nvarchar(4000)
  21958. declare @dest_owner   nvarchar(255)
  21959. declare @dest_tabname sysname
  21960. declare @src_objid    int
  21961. declare @artcolumns   binary(32)
  21962. declare @pkcolumns    binary(32)
  21963. declare @upd_cmd      nvarchar(255)
  21964. declare @dest_proc    sysname
  21965. declare @this_col     int
  21966. declare @art_col      int
  21967. declare @pkart_col    int
  21968. declare @isset        int
  21969. declare @pkcomputed   int
  21970. declare @typestring   nvarchar(255)
  21971. declare @spacer       nvarchar(10)
  21972. declare @pubid        int, @allow_queued_tran bit, @need_end bit
  21973.  
  21974. select @need_end = 0
  21975.  
  21976. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  21977. begin
  21978.     raiserror (14155, 16, 1 )
  21979.     return 1
  21980. end
  21981.  
  21982. -------- create temp table for command fragments
  21983.  
  21984. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  21985.  
  21986. -------- get sysarticles information
  21987.  
  21988. select @pubid = pubid, @dest_owner = dest_owner, @dest_tabname = dest_table, 
  21989.        @src_objid = objid, @artcolumns = columns, @upd_cmd = upd_cmd
  21990. from sysarticles
  21991. where artid = @artid
  21992.  
  21993. if @dest_owner is not null
  21994. begin
  21995.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  21996. end
  21997. else
  21998. begin
  21999.     select @dest_owner = N''
  22000. end
  22001.  
  22002. -------- get dest proc name
  22003.  
  22004. if( 1 != charindex( N'CALL', upper(@upd_cmd collate SQL_Latin1_General_CP1_CS_AS) ) ) or @upd_cmd is null
  22005. begin
  22006.     raiserror (14156, 16, 1 )
  22007.     return 1
  22008. end
  22009.  
  22010. select @allow_queued_tran = allow_queued_tran from syspublications where pubid = @pubid 
  22011.  
  22012. declare @keep_identity bit
  22013. if @allow_queued_tran = 1 and OBJECTPROPERTY(@src_objid, 'tablehasidentity') = 1
  22014.     select @keep_identity = 1
  22015. else
  22016.     select @keep_identity = 0
  22017.  
  22018. select @dest_proc = substring( @upd_cmd, 6, len( @upd_cmd ) - 4 )
  22019. select @cmd = N'if exists (select * from sysobjects where type = ''P'' and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  22020. insert into #proctext(procedure_text) values( @cmd )
  22021. insert into #proctext(procedure_text) values( N'go' )
  22022. insert into #proctext( procedure_text ) values (  N'create procedure ' + QUOTENAME(@dest_proc) + N' ')
  22023.  
  22024. -------- construct parameter list
  22025.  
  22026. exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  22027.  
  22028. exec dbo.sp_scriptupdateparams @src_objid, @artcolumns, @pkcolumns
  22029.  
  22030. insert into #proctext(procedure_text) values ( N'as' )
  22031.  
  22032. -------- now create the update statement
  22033.  
  22034. -- construct test to see if pk has changed 
  22035. -- only do this if the article has columns not included in the pk
  22036.  
  22037. exec @pkcomputed = sp_MSareallcolumnscomputed @src_objid, @pkcolumns
  22038.  
  22039. declare @pk_is_identity bit
  22040. select @pk_is_identity = 0
  22041.  
  22042. if @artcolumns != @pkcolumns and @pkcomputed = 0
  22043. begin
  22044.     select @cmd = N'if'
  22045.  
  22046.     select @art_col = 1
  22047.     select @pkart_col = 1
  22048.     select @spacer = ' '
  22049.  
  22050.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22051.     select colid from syscolumns where id = @src_objid order by colid asc
  22052.  
  22053.     OPEN hCColid
  22054.  
  22055.     FETCH hCColid INTO @this_col
  22056.  
  22057.     select @pk_is_identity = 1
  22058.     WHILE (@@fetch_status <> -1)
  22059.     begin
  22060.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22061.         if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  22062.         begin
  22063.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  22064.             if @isset != 0
  22065.             begin
  22066.                 if not (@keep_identity = 1 and 
  22067.                     columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  22068.                 begin
  22069.                     select @pk_is_identity = 0
  22070.                     select @cmd = @cmd + @spacer + N'@c'+convert( nvarchar, @art_col ) + N' = @pkc' + convert( nvarchar, @pkart_col ) 
  22071.                     select @spacer = N' and '
  22072.                     select @pkart_col = @pkart_col + 1
  22073.                     if len( @cmd ) > 3000
  22074.                     begin
  22075.                     insert into #proctext(procedure_text) values( @cmd )
  22076.                         select @cmd = N''
  22077.                     end
  22078.                 end
  22079.             end
  22080.             select @art_col = @art_col + 1
  22081.         end
  22082.         FETCH hCColid INTO @this_col
  22083.     end
  22084.  
  22085.     CLOSE hCColid
  22086.     DEALLOCATE hCColid
  22087.  
  22088.     if @pk_is_identity = 0
  22089.     begin
  22090.         insert into #proctext(procedure_text) values( @cmd )
  22091.  
  22092.         insert into #proctext(procedure_text) values( N'begin' )
  22093.  
  22094.         -- construct update if pk hasn't changed
  22095.  
  22096.         select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set'
  22097.  
  22098.         -- create SET clause
  22099.  
  22100.         select @art_col = 1
  22101.         select @spacer = N' '
  22102.  
  22103.         DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22104.         select colid from syscolumns where id = @src_objid order by colid asc
  22105.  
  22106.         OPEN hCColid
  22107.  
  22108.         FETCH hCColid INTO @this_col
  22109.         WHILE (@@fetch_status <> -1)
  22110.         begin
  22111.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22112.             if @isset != 0  and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  22113.             begin
  22114.                 exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  22115.                 if @isset = 0
  22116.                 begin
  22117.                     if not (@keep_identity = 1 and 
  22118.                         columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  22119.                     begin
  22120.                         select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = @c' + convert( nvarchar, @art_col ) 
  22121.                         select @spacer = N','
  22122.  
  22123.                         if len( @cmd ) > 3000
  22124.                         begin
  22125.                             insert into #proctext(procedure_text) values( @cmd )
  22126.                             select @cmd = N''
  22127.                         end
  22128.                     end
  22129.                 end
  22130.                 select @art_col = @art_col + 1
  22131.             end
  22132.             FETCH hCColid INTO @this_col
  22133.         end
  22134.         CLOSE hCColid
  22135.         DEALLOCATE hCColid
  22136.  
  22137.         insert into #proctext(procedure_text) values( @cmd )
  22138.  
  22139.         exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns
  22140.  
  22141.         if @allow_queued_tran <> 1
  22142.             exec dbo.sp_MSscript_missing_row_check
  22143.  
  22144.         insert into #proctext(procedure_text) values( N'end' )
  22145.         insert into #proctext(procedure_text) values( N'else' )
  22146.         insert into #proctext(procedure_text) values( N'begin' )
  22147.  
  22148.         select @need_end = 1
  22149.  
  22150.     end
  22151. end -- end if artcols != pkcols
  22152.  
  22153.  
  22154. -- construct update if pk has changed
  22155.  
  22156. select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set'
  22157.  
  22158. -- create SET clause
  22159.  
  22160. select @art_col = 1
  22161. select @spacer = N' '
  22162.  
  22163. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22164. select colid from syscolumns where id = @src_objid order by colid asc
  22165.  
  22166. OPEN hCColid
  22167.  
  22168. FETCH hCColid INTO @this_col
  22169. WHILE (@@fetch_status <> -1)
  22170. begin
  22171.     exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22172.     if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  22173.     begin
  22174.         if not (@keep_identity = 1 and 
  22175.             columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  22176.         begin
  22177.             select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = @c' + convert( nvarchar, @art_col ) 
  22178.             select @spacer = N','
  22179.  
  22180.             if len( @cmd ) > 3000
  22181.             begin
  22182.             insert into #proctext(procedure_text) values( @cmd )
  22183.                 select @cmd = N''
  22184.             end
  22185.         end
  22186.         select @art_col = @art_col + 1
  22187.     end
  22188.     FETCH hCColid INTO @this_col
  22189. end
  22190.  
  22191. CLOSE hCColid
  22192. DEALLOCATE hCColid
  22193.  
  22194. insert into #proctext(procedure_text) values( @cmd )
  22195.  
  22196. exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns
  22197.  
  22198. if @allow_queued_tran <> 1
  22199.     exec dbo.sp_MSscript_missing_row_check
  22200.  
  22201. if @need_end = 1
  22202.     insert into #proctext(procedure_text) values( N'end' )
  22203. -- flush to client
  22204.  
  22205. select procedure_text from #proctext order by c1 asc
  22206.  
  22207. go
  22208.  
  22209. EXEC dbo.sp_MS_marksystemobject sp_scriptupdproc
  22210. GO
  22211.  
  22212. --------------------------------------------------------------------------
  22213. --------------------------------------------------------------------------
  22214.  
  22215. print ''
  22216. print 'Creating procedure sp_scriptmappedupdproc'
  22217. go
  22218.  
  22219. create procedure sp_scriptmappedupdproc @artid int
  22220. as
  22221. declare @cmd          nvarchar(4000)
  22222. declare @dest_owner   nvarchar(255)
  22223. declare @dest_tabname sysname
  22224. declare @src_objid    int
  22225. declare @artcolumns   binary(32)
  22226. declare @pkcolumns    binary(32)
  22227. declare @upd_cmd      nvarchar(255)
  22228. declare @dest_proc    sysname
  22229. declare @art_cols     int
  22230. declare @this_col     int
  22231. declare @art_col      int
  22232. declare @pkart_col    int
  22233. declare @isset        int
  22234. declare @bytestr      nvarchar(10)
  22235. declare @bitstr       nvarchar(10)
  22236. declare @typestring   nvarchar(255)
  22237. declare @spacer       nvarchar(10)
  22238. declare @update_created  bit
  22239. declare @pkcomputed   int
  22240. declare @pubid        int, @allow_queued_tran bit
  22241.  
  22242. select @update_created     = 0
  22243.  
  22244. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  22245. begin
  22246.     raiserror (14155, 16, 1 )
  22247.     return 1
  22248. end
  22249.  
  22250. -------- create temp table for command fragments
  22251.  
  22252. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  22253.  
  22254. -------- get sysarticles information
  22255.  
  22256. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  22257.        @src_objid = objid, @artcolumns = columns, @upd_cmd = upd_cmd,
  22258.        @pubid = pubid
  22259. from sysarticles
  22260. where artid = @artid
  22261.  
  22262. if @dest_owner is not null
  22263. begin
  22264.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  22265. end
  22266. else
  22267. begin
  22268.     select @dest_owner = N''
  22269. end
  22270.  
  22271. -------- get dest proc name
  22272.  
  22273. if( 1 != charindex( N'MCALL', upper(@upd_cmd collate SQL_Latin1_General_CP1_CS_AS) ) ) or @upd_cmd is null
  22274. begin
  22275.     raiserror (14156, 16, 1 )
  22276.     return 1
  22277. end
  22278.  
  22279. select @allow_queued_tran = allow_queued_tran from syspublications where pubid = @pubid 
  22280.  
  22281. declare @keep_identity bit
  22282. if @allow_queued_tran = 1 and OBJECTPROPERTY(@src_objid, 'tablehasidentity') = 1
  22283.     select @keep_identity = 1
  22284. else
  22285.     select @keep_identity = 0
  22286.  
  22287. select @dest_proc = substring( @upd_cmd, 7, len( @upd_cmd ) - 5 )
  22288. select @cmd = N'if exists (select * from sysobjects where type = ''P''  and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  22289. insert into #proctext(procedure_text) values( @cmd )
  22290. insert into #proctext(procedure_text) values( N'go' )
  22291. insert into #proctext( procedure_text ) values ( N'create procedure ' + QUOTENAME(@dest_proc) + N' ' )
  22292.   
  22293.  
  22294. -------- construct parameter list
  22295.  
  22296. exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  22297.  
  22298. exec dbo.sp_scriptupdateparams @src_objid, @artcolumns, @pkcolumns
  22299.  
  22300. ----- add changed data bitmap
  22301.  
  22302. select @art_col = 1
  22303.  
  22304.  
  22305. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22306. select colid from syscolumns where id = @src_objid order by colid asc
  22307.  
  22308. OPEN hCColid
  22309.  
  22310. FETCH hCColid INTO @this_col
  22311.  
  22312. WHILE (@@fetch_status <> -1)
  22313. begin
  22314.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22315.    if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  22316.    begin
  22317.         select @art_col = @art_col + 1
  22318.    end
  22319.    FETCH hCColid INTO @this_col
  22320. end
  22321. CLOSE hCColid
  22322. DEALLOCATE hCColid
  22323.  
  22324. -- Note that bitmap size is based on number of article columns
  22325. -- (computed by loop above) not source table columns
  22326.  
  22327. select @cmd = N',@bitmap binary(' + convert(nvarchar,1+(@art_col-1) / 8) + N')'
  22328.  
  22329. insert into #proctext(procedure_text) values( @cmd )
  22330. insert into #proctext(procedure_text) values( N'as' )
  22331.  
  22332.  
  22333. -- construct IF statement to examine colbitmap and determine if a 
  22334. -- primary key column has been updated.  
  22335.  
  22336. -- do this only if the article contains columns not included in the pk
  22337. -- and at least one of the columns in the PK is real ( i.e. not computed )
  22338.  
  22339. -- note that if all the article columns are PK columns, we will
  22340. -- construct the 'update all columns including PK columns' statement
  22341. -- w/o a preceeding IF, and we will NOT construct the 'only update non-pk columns' 
  22342. -- part of the procedure
  22343.  
  22344. -- also note that this is pretty much worthless since 7.0 and above are
  22345. -- guaranteed to NEVER generate an UPDATE if a PK columns is updated... oh well.
  22346. declare @pk_is_identity bit
  22347. select @pk_is_identity = 0
  22348.  
  22349. exec @pkcomputed = sp_MSareallcolumnscomputed @src_objid, @pkcolumns
  22350.  
  22351. if @artcolumns != @pkcolumns and @pkcomputed = 0
  22352. begin
  22353.     select @art_col = 1
  22354.     select @spacer = N' '
  22355.  
  22356.     select @cmd = N'if'
  22357.  
  22358.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22359.     select colid from syscolumns where id = @src_objid order by colid asc
  22360.  
  22361.     OPEN hCColid
  22362.  
  22363.     FETCH hCColid INTO @this_col
  22364.  
  22365.     select @pk_is_identity = 1
  22366.  
  22367.     WHILE (@@fetch_status <> -1)
  22368.     begin
  22369.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22370.         if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  22371.         begin 
  22372.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  22373.             if @isset != 0
  22374.             begin
  22375.                 if not (@keep_identity = 1 and 
  22376.                     columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  22377.                 begin
  22378.                     select @pk_is_identity = 0
  22379.                     select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 )
  22380.                     select @bitstr =  convert( nvarchar, power(2, (@art_col-1) % 8 ) )
  22381.  
  22382.                     select @cmd = @cmd + @spacer + N'substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr +  
  22383.                              N' = ' + @bitstr 
  22384.                 
  22385.                     select @spacer = N' or '
  22386.  
  22387.                     if len( @cmd ) > 3000
  22388.                     begin
  22389.                         insert into #proctext(procedure_text) values( @cmd )
  22390.                         select @cmd = N''
  22391.                     end
  22392.                 end
  22393.             end
  22394.             select @art_col = @art_col + 1
  22395.         end
  22396.         FETCH hCColid INTO @this_col
  22397.     end
  22398.     CLOSE hCColid
  22399.     DEALLOCATE hCColid
  22400.  
  22401.     if @pk_is_identity = 0
  22402.         insert into #proctext(procedure_text) values( @cmd )
  22403.  
  22404. end  -- if artcolumns != pkcolumns
  22405.  
  22406. -- construct update statement including PK columns
  22407.  
  22408. insert into #proctext(procedure_text) values( N'begin' )
  22409.  
  22410. insert into #proctext(procedure_text) values( N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set' )
  22411.  
  22412. -- create SET clause consisting of CASE statements
  22413.  
  22414. select @art_col = 1
  22415. select @spacer = N''
  22416.  
  22417. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22418. select colid from syscolumns where id = @src_objid order by colid asc
  22419.  
  22420. OPEN hCColid
  22421.  
  22422. FETCH hCColid INTO @this_col
  22423.  
  22424. WHILE (@@fetch_status <> -1)
  22425. begin
  22426.     exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22427.     if @isset != 0  and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  22428.     begin
  22429.         if not (@keep_identity = 1 and 
  22430.             columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  22431.         begin
  22432.             select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 )
  22433.             select @bitstr =  convert( nvarchar, power(2, (@art_col-1) % 8 ) )
  22434.  
  22435.             insert into #proctext(procedure_text) values (
  22436.                  @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = case substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr +  
  22437.                  N' when ' + @bitstr + N' then ' + N'@c'+ convert( nvarchar, @art_col ) + 
  22438.                  N' else ' + QUOTENAME(col_name( @src_objid, @this_col)) + N' end' )
  22439.  
  22440.             select @spacer = ',' 
  22441.         end
  22442.  
  22443.         select @art_col = @art_col + 1
  22444.     end
  22445.     FETCH hCColid INTO @this_col
  22446. end
  22447. CLOSE hCColid
  22448. DEALLOCATE hCColid
  22449.  
  22450. -- create where clause
  22451.  
  22452. exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns
  22453.  
  22454. if @allow_queued_tran <> 1
  22455.     exec dbo.sp_MSscript_missing_row_check
  22456.  
  22457. -- construct UPDATE that does not set PK cols
  22458. -- only do this if the article contains columns that are not included
  22459. -- in the pk
  22460.  
  22461. if @artcolumns != @pkcolumns  and @pkcomputed = 0 and @pk_is_identity = 0
  22462. begin
  22463.  
  22464.     -- create SET clause consisting of CASE statements
  22465.  
  22466.     select @art_col = 1
  22467.     select @spacer = N''
  22468.  
  22469.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22470.     select colid from syscolumns where id = @src_objid order by colid asc
  22471.  
  22472.     OPEN hCColid
  22473.  
  22474.     FETCH hCColid INTO @this_col
  22475.  
  22476.     WHILE (@@fetch_status <> -1)
  22477.     begin
  22478.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22479.         if @isset != 0  and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  22480.         begin
  22481.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns 
  22482.             if @isset = 0 
  22483.             begin
  22484.                 if not (@keep_identity = 1 and 
  22485.                     columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  22486.                 begin
  22487.                     if (@update_created = 0)
  22488.                     begin
  22489.                         insert into #proctext(procedure_text) values( N'end' )
  22490.                         insert into #proctext(procedure_text) values( N'else' )
  22491.                         insert into #proctext(procedure_text) values( N'begin' )
  22492.                         insert into #proctext(procedure_text) values( N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set' )
  22493.                         select @update_created = 1
  22494.                     end
  22495.                     select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 )
  22496.                     select @bitstr =  convert( nvarchar, power(2, (@art_col-1) % 8 ) )
  22497.  
  22498.                     insert into #proctext(procedure_text) values (
  22499.                          @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = case substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr +  
  22500.                          N' when ' + @bitstr + N' then ' + N'@c'+ convert( nvarchar, @art_col ) + 
  22501.                          N' else ' + QUOTENAME(col_name( @src_objid, @this_col)) + N' end' )
  22502.  
  22503.                     select @spacer = ',' 
  22504.                 end
  22505.             end
  22506.             select @art_col = @art_col + 1
  22507.         end
  22508.            FETCH hCColid INTO @this_col
  22509.     end
  22510.     CLOSE hCColid
  22511.     DEALLOCATE hCColid
  22512.  
  22513.     if @update_created = 1
  22514.     begin
  22515.         exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns
  22516.         if @allow_queued_tran <> 1
  22517.             exec dbo.sp_MSscript_missing_row_check
  22518.     end
  22519.  
  22520. end
  22521.  
  22522. insert into #proctext(procedure_text) values( N'end' )
  22523. select procedure_text from #proctext order by c1 asc
  22524.  
  22525. go
  22526.  
  22527. EXEC dbo.sp_MS_marksystemobject sp_scriptmappedupdproc
  22528. GO
  22529.  
  22530. --------------------------------------------------------------------------
  22531. --------------------------------------------------------------------------
  22532.  
  22533. print ''
  22534. print 'Creating procedure sp_scriptdynamicupdproc'
  22535. go
  22536.  
  22537. create procedure sp_scriptdynamicupdproc @artid int
  22538. as
  22539. declare @cmd          nvarchar(4000)
  22540. declare @dest_owner   nvarchar(255)
  22541. declare @dest_tabname sysname
  22542. declare @src_objid    int
  22543. declare @artcolumns   binary(32)
  22544. declare @pkcolumns    binary(32)
  22545. declare @upd_cmd      nvarchar(255)
  22546. declare @dest_proc    sysname
  22547. declare @art_cols     int
  22548. declare @this_col     int
  22549. declare @art_col      int
  22550. declare @pk_col       int
  22551. declare @pkart_col    int
  22552. declare @isset        int
  22553. declare @ispk         int
  22554. declare @isidentity   bit
  22555. declare @iscomputed   bit
  22556. declare @bytestr      nvarchar(10)
  22557. declare @bitstr       nvarchar(10)
  22558. declare @typestring   nvarchar(255)
  22559. declare @spacer_param nvarchar(10)
  22560. declare @update_created  bit
  22561. declare @pkcomputed   int
  22562. declare @pubid        int, @allow_queued_tran bit
  22563.  
  22564. set nocount on 
  22565.  
  22566. select @update_created     = 0
  22567.  
  22568. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  22569. begin
  22570.     raiserror (14155, 16, 1 )
  22571.     return 1
  22572. end
  22573.  
  22574. -------- create temp table for command fragments
  22575.  
  22576. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  22577. create table #proctext_params ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  22578. create table #proctext_paramdef ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  22579. create table #proctext_pkparams ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  22580.  
  22581.  
  22582.  
  22583. -------- get sysarticles information
  22584.  
  22585. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  22586.        @src_objid = objid, @artcolumns = columns, @upd_cmd = upd_cmd,
  22587.        @pubid = pubid
  22588. from sysarticles
  22589. where artid = @artid
  22590.  
  22591. if @dest_owner is not null
  22592. begin
  22593.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  22594. end
  22595. else
  22596. begin
  22597.     select @dest_owner = N''
  22598. end
  22599.  
  22600. -------- get dest proc name
  22601.  
  22602. if( 1 != charindex( N'MCALL', upper(@upd_cmd) ) ) or @upd_cmd is null
  22603. begin
  22604.     raiserror (14156, 16, 1 )
  22605.     return 1
  22606. end
  22607.  
  22608. select @allow_queued_tran = allow_queued_tran from syspublications where pubid = @pubid 
  22609.  
  22610. declare @keep_identity bit
  22611. if @allow_queued_tran = 1 and OBJECTPROPERTY(@src_objid, 'tablehasidentity') = 1
  22612.     select @keep_identity = 1
  22613. else
  22614.     select @keep_identity = 0
  22615.  
  22616. select @dest_proc = substring( @upd_cmd, 7, len( @upd_cmd ) - 5 )
  22617. select @cmd = N'if exists (select * from sysobjects where type = ''P''  and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  22618. insert into #proctext(procedure_text) values( @cmd )
  22619. insert into #proctext(procedure_text) values( N'go' )
  22620. insert into #proctext( procedure_text ) values ( N'create procedure ' + QUOTENAME(@dest_proc) + N' ' )
  22621.   
  22622.  
  22623. -------- construct parameter list
  22624.  
  22625. exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  22626.  
  22627. exec dbo.sp_scriptupdateparams @src_objid, @artcolumns, @pkcolumns
  22628.  
  22629. ----- add changed data bitmap
  22630.  
  22631. select @art_col = 1
  22632. select @pk_col = 1
  22633.  
  22634. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22635. select colid from syscolumns where id = @src_objid order by colid asc
  22636.  
  22637. OPEN hCColid
  22638.  
  22639. FETCH hCColid INTO @this_col
  22640.  
  22641. WHILE (@@fetch_status <> -1)
  22642. begin
  22643.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22644.    if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  22645.    begin
  22646.         select @art_col = @art_col + 1
  22647.    end
  22648.    FETCH hCColid INTO @this_col
  22649. end
  22650. CLOSE hCColid
  22651. DEALLOCATE hCColid
  22652.  
  22653. -- Note that bitmap size is based on number of article columns
  22654. -- (computed by loop above) not source table columns
  22655.  
  22656. select @cmd = N',@bitmap binary(' + convert(nvarchar,1+(@art_col-1) / 8) + N')'
  22657.  
  22658. insert into #proctext(procedure_text) values( @cmd )
  22659. insert into #proctext(procedure_text) values( N'as' )
  22660.  
  22661.  
  22662.  
  22663. -- Find out if pk is identity
  22664. declare @pk_is_identity bit
  22665. select @pk_is_identity = 0
  22666.  
  22667. exec @pkcomputed = sp_MSareallcolumnscomputed @src_objid, @pkcolumns
  22668.  
  22669. if @artcolumns != @pkcolumns and @pkcomputed = 0
  22670. begin
  22671.     select @art_col = 1
  22672.  
  22673.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22674.     select colid from syscolumns where id = @src_objid order by colid asc
  22675.  
  22676.     OPEN hCColid
  22677.  
  22678.     FETCH hCColid INTO @this_col
  22679.  
  22680.     select @pk_is_identity = 1
  22681.  
  22682.     WHILE (@@fetch_status <> -1)
  22683.     begin
  22684.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22685.         if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  22686.         begin 
  22687.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  22688.             if @isset != 0
  22689.             begin
  22690.                 if not (@keep_identity = 1 and 
  22691.                     columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  22692.                 begin
  22693.                     select @pk_is_identity = 0
  22694.                 end
  22695.             end
  22696.             select @art_col = @art_col + 1
  22697.         end
  22698.         FETCH hCColid INTO @this_col
  22699.     end
  22700.     CLOSE hCColid
  22701.     DEALLOCATE hCColid
  22702. end 
  22703.  
  22704. -- construct UPDATE that does not set PK cols
  22705. -- only do this if the article contains columns that are not included
  22706. -- in the pk
  22707. -- Note: we assume pk columns never change. pk changes will be replicated
  22708. -- as delete insert.
  22709.  
  22710. if @artcolumns != @pkcolumns  and @pkcomputed = 0 and @pk_is_identity = 0
  22711. begin
  22712.  
  22713.     -- create SET clause consisting of CASE statements
  22714.  
  22715.     select @art_col = 1
  22716.     select @spacer_param = N''
  22717.  
  22718.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22719.     select colid from syscolumns where id = @src_objid order by colid asc
  22720.  
  22721.     OPEN hCColid
  22722.  
  22723.     FETCH hCColid INTO @this_col
  22724.  
  22725.     WHILE (@@fetch_status <> -1)
  22726.     begin
  22727.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22728.         if @isset != 0  
  22729.         begin
  22730.             exec @ispk = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  22731.             
  22732.             if EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  22733.                 select @iscomputed = 0
  22734.             else
  22735.                 select @iscomputed = 1
  22736.             
  22737.             if (@keep_identity = 1 and 
  22738.                     columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)  
  22739.                 select @isidentity = 1
  22740.             else
  22741.                 select @isidentity = 0
  22742.                 
  22743.             -- If not pk, not computed and not identity    
  22744.             if @ispk = 0 and @iscomputed = 0 and @isidentity = 0
  22745.             begin
  22746.                 if (@update_created = 0)
  22747.                 begin
  22748.                     insert into #proctext(procedure_text) values( 
  22749.                         N'declare @stmt nvarchar(4000), @spacer nvarchar(1)')
  22750.  
  22751.                     insert into #proctext(procedure_text) values( 
  22752.                         N'select @spacer =N''''')
  22753.  
  22754.                     insert into #proctext(procedure_text) values( 
  22755.                         N'select @stmt = N''update ' + 
  22756.                         replace(@dest_owner + QUOTENAME(@dest_tabname), N'''', N'''''' ) +
  22757.                         N' set ''')
  22758.  
  22759.                     select @update_created = 1
  22760.                 end
  22761.  
  22762.                 select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 )
  22763.                 select @bitstr =  convert( nvarchar, power(2, (@art_col-1) % 8 ) )
  22764.  
  22765.                 insert into #proctext(procedure_text) values (
  22766.                      N'if substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr +  
  22767.                      N' = ' + @bitstr)
  22768.  
  22769.                 insert into #proctext(procedure_text) values (N'begin')
  22770.  
  22771.                 -- Append statement
  22772.                 insert into #proctext(procedure_text) values (
  22773.                      N'select @stmt = @stmt + @spacer + ' + 
  22774.                      N'N''' + replace(QUOTENAME(col_name( @src_objid, @this_col)), N'''', N'''''') + N''' + ' +
  22775.                      N'N''=@'+ convert( nvarchar, @art_col ) + N'''')
  22776.  
  22777.                 -- Set @spacer is the proc
  22778.                 insert into #proctext(procedure_text) values (
  22779.                     N'select @spacer = N'',''')
  22780.  
  22781.                 insert into #proctext(procedure_text) values (N'end')
  22782.             end
  22783.             -- If pk or (not computed and not identity) add the param
  22784.             if @ispk <> 0 or (@iscomputed = 0 and @isidentity = 0)
  22785.             begin
  22786.                 -- Add to param list
  22787.                 if (@ispk <> 0)
  22788.                   begin
  22789.                     -- Use primary key value
  22790.                     insert into #proctext_params(procedure_text) values( 
  22791.                         @spacer_param + N'@pkc' + convert( nvarchar, @pk_col ))
  22792.  
  22793.                     -- Increment primary key counter
  22794.                     select @pk_col = @pk_col + 1;
  22795.  
  22796.                   end
  22797.                 else
  22798.                     -- Use column value
  22799.                     insert into #proctext_params(procedure_text) values( 
  22800.                         @spacer_param + N'@c' + convert( nvarchar, @art_col ))
  22801.  
  22802.                 -- Get type str
  22803.                 exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  22804.  
  22805.                 -- Append typedef
  22806.                 insert into #proctext_paramdef(procedure_text) values (
  22807.                      @spacer_param + N'@' + convert( nvarchar, @art_col ) + 
  22808.                      N' ' + @typestring )
  22809.  
  22810.                 select @spacer_param = ',' 
  22811.             end
  22812.  
  22813.             select @art_col = @art_col + 1
  22814.         end
  22815.            FETCH hCColid INTO @this_col
  22816.     end
  22817.     CLOSE hCColid
  22818.     DEALLOCATE hCColid
  22819.  
  22820.     if @update_created = 1
  22821.     begin
  22822.  
  22823.         -- Append statement of the start of where clause
  22824.         insert into #proctext(procedure_text) values (
  22825.              N'    select @stmt = @stmt + N'' ')
  22826.  
  22827.         -- Escape ' in the where clause
  22828.         declare @low_mark int, @high_mark int
  22829.         select @low_mark = max(c1) from #proctext
  22830.         -- Pass in @artcolumns so that the where clause will use the ordinal in the
  22831.         -- article bit map rather then one in pk bitmap. This is consistent with
  22832.         -- the type def string.
  22833.         -- UNDONE: change comments in sp_scriptpkwhereclause
  22834.         -- Use prefix '@' to be consistent with type def string
  22835.         exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns, '@', @artcolumns
  22836.         select @high_mark = max(c1) from #proctext
  22837.         update #proctext set procedure_text = replace ( procedure_text, N'''', N'''''') 
  22838.             where c1 > @low_mark and c1 <= @high_mark
  22839.  
  22840.         -- Close the where clause
  22841.         insert into #proctext(procedure_text) values (
  22842.              N'''')
  22843.  
  22844.         -- Add call to sql_executesql and the param list
  22845.         insert into #proctext(procedure_text) values( 
  22846.             N'exec sp_executesql @stmt, N'' ')
  22847.  
  22848.         -- Add param def
  22849.         insert into #proctext(procedure_text) 
  22850.             select procedure_text from #proctext_paramdef order by c1 asc
  22851.  
  22852.         -- Close the param def
  22853.         insert into #proctext(procedure_text) values (
  22854.              N''',')
  22855.  
  22856.         -- Add param list
  22857.         insert into #proctext(procedure_text) 
  22858.             select procedure_text from #proctext_params order by c1 asc
  22859.  
  22860.         if @allow_queued_tran <> 1
  22861.             exec dbo.sp_MSscript_missing_row_check
  22862.     end
  22863.  
  22864. end
  22865.  
  22866. select procedure_text from #proctext order by c1 asc
  22867.  
  22868. go
  22869.  
  22870. EXEC dbo.sp_MS_marksystemobject sp_scriptdynamicupdproc
  22871. GO
  22872.  
  22873. ----------------------------------------------------------------------------------------------
  22874. ----------------------------------------------------------------------------------------------
  22875.  
  22876. print ''
  22877. print 'Creating procedure sp_scriptxupdproc'
  22878. go
  22879.  
  22880. create procedure sp_scriptxupdproc @artid int
  22881. as
  22882. declare @cmd          nvarchar(4000),
  22883.         @dest_owner   nvarchar(255),
  22884.         @dest_tabname sysname,
  22885.         @src_objid    int,
  22886.         @artcolumns   binary(32),
  22887.         @pkcolumns    binary(32),
  22888.         @upd_cmd      nvarchar(255),
  22889.         @dest_proc    sysname,
  22890.         @this_col     int,
  22891.         @art_col      int,
  22892.         --@pkart_col    int,
  22893.         @isset        int,
  22894.         @pkcomputed   int,
  22895.         @typestring   nvarchar(255),
  22896.         @spacer       nvarchar(10),
  22897.         @pubid          int, 
  22898.         @param_count  int
  22899.         ,@queued_check bit, @exists_else bit
  22900.         ,@qwhere_string nvarchar(4000)
  22901.  
  22902. set nocount on
  22903. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  22904. begin
  22905.     raiserror (14155, 16, 1 )
  22906.     return 1
  22907. end
  22908.  
  22909. select @exists_else = 0
  22910.  
  22911. -------- create temp table for command fragments
  22912.  
  22913. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  22914.  
  22915. -------- get sysarticles information
  22916.  
  22917. select @pubid = pubid, @dest_owner = dest_owner, @dest_tabname = dest_table, 
  22918.        @src_objid = objid, @artcolumns = columns, @upd_cmd = upd_cmd
  22919. from sysarticles
  22920. where artid = @artid
  22921.  
  22922. if @dest_owner is not null
  22923. begin
  22924.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  22925. end
  22926. else
  22927. begin
  22928.     select @dest_owner = N''
  22929. end
  22930.  
  22931. -- Check if this is a queued publication
  22932. select @queued_check = ISNULL(allow_queued_tran, 0) 
  22933. from syspublications
  22934. where pubid = @pubid
  22935.  
  22936. -------- get dest proc name
  22937.  
  22938. if( 1 != charindex( N'XCALL', upper(@upd_cmd collate SQL_Latin1_General_CP1_CS_AS) ) ) or @upd_cmd is null
  22939. begin
  22940.     raiserror (14156, 16, 1 )
  22941.     return 1
  22942. end
  22943.  
  22944. declare @keep_identity bit
  22945. if exists (select * from syspublications where pubid = @pubid and
  22946.     allow_queued_tran = 1) and OBJECTPROPERTY(@src_objid, 'tablehasidentity') = 1
  22947.     select @keep_identity = 1
  22948. else
  22949.     select @keep_identity = 0
  22950.  
  22951. select @dest_proc = substring( @upd_cmd, 7, len( @upd_cmd ) - 5 )
  22952. select @cmd = N'if exists (select * from sysobjects where type = ''P''  and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  22953. insert into #proctext(procedure_text) values( @cmd )
  22954. insert into #proctext(procedure_text) values( N'go' )
  22955. insert into #proctext( procedure_text ) values (  N'create procedure ' + QUOTENAME(@dest_proc) + N' ')
  22956.  
  22957. -------- construct parameter list
  22958.  
  22959. exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  22960.  
  22961. -- Send null as @pkcolumns. We don't need pk parameters.
  22962. exec dbo.sp_scriptupdateparams @src_objid, @artcolumns, NULL, @param_count output
  22963.  
  22964. insert into #proctext(procedure_text) values ( N'as' )
  22965.  
  22966. -------- now create the update statement
  22967.  
  22968. -- construct test to see if pk has changed 
  22969. -- only do this if the article has columns not included in the pk
  22970.  
  22971. exec @pkcomputed = sp_MSareallcolumnscomputed @src_objid, @pkcolumns
  22972.  
  22973. declare @pk_is_identity bit
  22974. select @pk_is_identity = 0
  22975.  
  22976. if @artcolumns != @pkcolumns and @pkcomputed = 0
  22977. begin
  22978.     select @cmd = N'if'
  22979.  
  22980.     select @art_col = 1
  22981.     --select @pkart_col = 1
  22982.     select @spacer = ' '
  22983.  
  22984.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22985.     select colid from syscolumns where id = @src_objid order by colid asc
  22986.  
  22987.     OPEN hCColid
  22988.  
  22989.     FETCH hCColid INTO @this_col
  22990.  
  22991.     select @pk_is_identity = 1
  22992.     WHILE (@@fetch_status <> -1)
  22993.     begin
  22994.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22995.         if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  22996.         begin
  22997.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  22998.             if @isset != 0
  22999.             begin
  23000.                 if not (@keep_identity = 1 and 
  23001.                     columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  23002.                 begin
  23003.                     select @pk_is_identity = 0
  23004.                     select @cmd = @cmd + @spacer + N'@c'+convert( nvarchar, @art_col + @param_count/2) + 
  23005.                         N' = @c' + convert( nvarchar, @art_col ) 
  23006.                     select @spacer = N' and '
  23007.                     --select @pkart_col = @pkart_col + 1
  23008.                     if len( @cmd ) > 3000
  23009.                     begin
  23010.                     insert into #proctext(procedure_text) values( @cmd )
  23011.                         select @cmd = N''
  23012.                     end
  23013.                 end
  23014.             end
  23015.             select @art_col = @art_col + 1
  23016.         end
  23017.         FETCH hCColid INTO @this_col
  23018.     end
  23019.  
  23020.     CLOSE hCColid
  23021.     DEALLOCATE hCColid
  23022.  
  23023.     if @pk_is_identity = 0
  23024.     begin
  23025.         insert into #proctext(procedure_text) values( @cmd )
  23026.  
  23027.         insert into #proctext(procedure_text) values( N'begin' )
  23028.  
  23029.         -- construct update if pk hasn't changed
  23030.         -- We know that there would be a least one column for the update below, even if
  23031.         -- the columns outside the pk are identity or timestamp. Since identity and timestamp
  23032.         -- will be mapped off unless it is queued tran. In that case, we have 'msrepl_tran_version'
  23033.         select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set'
  23034.  
  23035.         -- create SET clause
  23036.  
  23037.         select @art_col = 1
  23038.         select @spacer = N' '
  23039.  
  23040.         DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  23041.         select colid from syscolumns where id = @src_objid order by colid asc
  23042.  
  23043.         OPEN hCColid
  23044.  
  23045.         FETCH hCColid INTO @this_col
  23046.         WHILE (@@fetch_status <> -1)
  23047.         begin
  23048.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  23049.             if @isset != 0  and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  23050.             begin
  23051.                 exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  23052.                 if @isset = 0
  23053.                 begin
  23054.                     if not (@keep_identity = 1 and 
  23055.                         columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  23056.                     begin
  23057.                         select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + 
  23058.                             N' = @c' + convert( nvarchar, @art_col + @param_count/2) 
  23059.                         select @spacer = N','
  23060.  
  23061.                         if len( @cmd ) > 3000
  23062.                         begin
  23063.                             insert into #proctext(procedure_text) values( @cmd )
  23064.                             select @cmd = N''
  23065.                         end
  23066.  
  23067.                         --
  23068.                         -- Queued processing:if this is the row version column : need to add to where clause
  23069.                         --
  23070.                         if ((@queued_check = 1) and (col_name( @src_objid, @this_col) = N'msrepl_tran_version'))
  23071.                             select @qwhere_string = N' and msrepl_tran_version = @c' + convert( nvarchar, @art_col )                        
  23072.                     end
  23073.                 end
  23074.                 select @art_col = @art_col + 1
  23075.             end
  23076.             FETCH hCColid INTO @this_col
  23077.         end
  23078.         CLOSE hCColid
  23079.         DEALLOCATE hCColid
  23080.  
  23081.         insert into #proctext(procedure_text) values( @cmd )
  23082.  
  23083.         exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns, N'@c', @artcolumns
  23084.         if (@queued_check = 1)
  23085.             insert into #proctext(procedure_text) values( @qwhere_string )
  23086.         else
  23087.             exec dbo.sp_MSscript_missing_row_check
  23088.  
  23089.         insert into #proctext(procedure_text) values( N'end' )
  23090.         insert into #proctext(procedure_text) values( N'else' )
  23091.         insert into #proctext(procedure_text) values( N'begin' )
  23092.  
  23093.         select @exists_else = 1
  23094.  
  23095.     end
  23096. end -- end if artcols != pkcols
  23097.  
  23098.  
  23099. -- construct update if pk has changed
  23100. select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set'
  23101.  
  23102. -- create SET clause
  23103.  
  23104. select @art_col = 1
  23105. select @spacer = N' '
  23106.  
  23107. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  23108. select colid from syscolumns where id = @src_objid order by colid asc
  23109.  
  23110. OPEN hCColid
  23111.  
  23112. FETCH hCColid INTO @this_col
  23113. WHILE (@@fetch_status <> -1)
  23114. begin
  23115.     exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  23116.     if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  23117.     begin
  23118.         if not (@keep_identity = 1 and 
  23119.             columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  23120.         begin
  23121.             select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + 
  23122.                 N' = @c' + convert( nvarchar, @art_col + @param_count/2 ) 
  23123.             select @spacer = N','
  23124.  
  23125.             if len( @cmd ) > 3000
  23126.             begin
  23127.             insert into #proctext(procedure_text) values( @cmd )
  23128.                 select @cmd = N''
  23129.             end
  23130.  
  23131.             --
  23132.             -- Queued processing:if this is the row version column : need to add to where clause
  23133.             --
  23134.             if ((@queued_check = 1) and (col_name( @src_objid, @this_col) = N'msrepl_tran_version'))
  23135.                 select @qwhere_string = N' and msrepl_tran_version = @c' + convert( nvarchar, @art_col )                        
  23136.         end
  23137.         select @art_col = @art_col + 1
  23138.     end
  23139.     FETCH hCColid INTO @this_col
  23140. end
  23141.  
  23142. CLOSE hCColid
  23143. DEALLOCATE hCColid
  23144.  
  23145. insert into #proctext(procedure_text) values( @cmd )
  23146.  
  23147. exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns, N'@c', @artcolumns
  23148. if (@queued_check = 1)
  23149.     insert into #proctext(procedure_text) values( @qwhere_string ) 
  23150. else
  23151.     exec dbo.sp_MSscript_missing_row_check
  23152.  
  23153. if @exists_else = 1
  23154.     insert into #proctext(procedure_text) values( N'end' )
  23155.  
  23156. -- flush to client
  23157.  
  23158. select procedure_text from #proctext order by c1 asc
  23159.  
  23160. go
  23161.  
  23162. EXEC dbo.sp_MS_marksystemobject sp_scriptxupdproc
  23163. GO
  23164.  
  23165. --------------------------------------------------------------------------
  23166. --------------------------------------------------------------------------
  23167.  
  23168. print ''
  23169. print 'Creating procedure sp_MSscriptmvastablenci'
  23170. go
  23171.  
  23172. create procedure sp_MSscriptmvastablenci @artid int
  23173. as
  23174. declare @cmd          nvarchar(4000)
  23175. declare @dest_owner   nvarchar(255)
  23176. declare @dest_tabname sysname
  23177. declare @src_objid    int
  23178. declare @constraint_name  sysname
  23179. declare @spacer          nvarchar(1)
  23180. declare @srcobj          nvarchar(1000)
  23181. declare @colname      sysname
  23182. declare @indkey          int
  23183. declare @indid          int
  23184. declare @status          int
  23185. declare @unique          nvarchar(10)
  23186. declare @cmd_sep      nvarchar(10)
  23187.  
  23188. -------- create temp table for command fragments
  23189.  
  23190. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  23191.  
  23192. -------- get sysarticles information
  23193.  
  23194. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  23195.        @src_objid = objid
  23196. from sysarticles
  23197. where artid = @artid
  23198.  
  23199. if @dest_owner is not null
  23200. begin
  23201.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  23202. end
  23203. else
  23204. begin
  23205.     select @dest_owner = N''
  23206. end
  23207.  
  23208. select @srcobj = QUOTENAME( USER_NAME(OBJECTPROPERTY(@src_objid,'OwnerId'))) collate database_default + N'.' + QUOTENAME(object_name(@src_objid)) collate database_default
  23209. select @cmd_sep = N''
  23210.  
  23211. DECLARE hCIdx CURSOR LOCAL FAST_FORWARD FOR
  23212. select name, indid, status from sysindexes where id = @src_objid and indid > 1 order by indid asc
  23213.  
  23214. OPEN hCIdx
  23215. FETCH hCIdx INTO @constraint_name, @indid, @status
  23216.  
  23217. WHILE (@@fetch_status <> -1)
  23218. begin
  23219.     if @status & 2 = 2
  23220.     begin
  23221.         select @unique = N' unique '
  23222.     end
  23223.     else
  23224.     begin
  23225.         select @unique = N' '
  23226.     end
  23227.  
  23228.     insert into #proctext(procedure_text) values( @cmd_sep )
  23229.     select @cmd_sep = N'GO'
  23230.  
  23231.     select @cmd = N'create' + @unique + N'nonclustered index ' + QUOTENAME(@constraint_name) + N' on ' +@dest_owner + QUOTENAME(@dest_tabname) + N'('
  23232.     insert into #proctext(procedure_text) values( @cmd )
  23233.  
  23234.     select @spacer = N' '
  23235.     select @cmd = N''
  23236.  
  23237.     select @indkey = 1
  23238.     while (@indkey <= 16)
  23239.     begin    
  23240.         select @colname = index_col(@srcobj, @indid, @indkey)
  23241.         if (@colname is null)
  23242.         begin
  23243.             select @indkey = 16
  23244.         end
  23245.         else
  23246.         begin
  23247.             select @cmd = @cmd + @spacer + QUOTENAME(@colname)
  23248.             select @spacer = N','
  23249.  
  23250.             if len( @cmd ) > 3000
  23251.             begin
  23252.                 insert into #proctext(procedure_text) values( @cmd )
  23253.                 select @cmd = N''
  23254.             end
  23255.         end
  23256.         select @indkey = @indkey + 1
  23257.     end
  23258.  
  23259.     insert into #proctext(procedure_text) values( @cmd )
  23260.     insert into #proctext(procedure_text) values( N')' )
  23261.     
  23262.     FETCH hCIdx INTO @constraint_name, @indid, @status
  23263. end
  23264.  
  23265. CLOSE hCIdx
  23266. DEALLOCATE hCIdx
  23267. select procedure_text from #proctext order by c1 asc
  23268.  
  23269. go
  23270. EXEC dbo.sp_MS_marksystemobject sp_MSscriptmvastablenci
  23271. GO
  23272.  
  23273. print ''
  23274. print 'Creating procedure sp_MSscriptmvastablepkc'
  23275. go
  23276.  
  23277. create procedure sp_MSscriptmvastablepkc @artid int
  23278. as
  23279. declare @cmd          nvarchar(4000)
  23280. declare @dest_owner   nvarchar(255)
  23281. declare @dest_tabname sysname
  23282. declare @src_objid    int
  23283. declare @constraint_name  sysname
  23284. declare @spacer          nvarchar(1)
  23285. declare @srcobj          nvarchar(1000)
  23286. declare @colname      sysname
  23287. declare @indkey          int
  23288. declare @indid          int
  23289.  
  23290. -------- create temp table for command fragments
  23291.  
  23292. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  23293.  
  23294. -------- get sysarticles information
  23295.  
  23296. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  23297.        @src_objid = objid
  23298. from sysarticles
  23299. where artid = @artid
  23300.  
  23301. if @dest_owner is not null
  23302. begin
  23303.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  23304. end
  23305. else
  23306. begin
  23307.     select @dest_owner = N''
  23308. end
  23309.  
  23310. select @srcobj = QUOTENAME( USER_NAME(OBJECTPROPERTY(@src_objid,'OwnerId'))) collate database_default + N'.' + QUOTENAME(object_name(@src_objid)) collate database_default
  23311.  
  23312. select @constraint_name = name, @indid = indid from sysindexes where id = @src_objid and status & 16 <> 0
  23313.  
  23314. select @cmd = N'alter table ' + @dest_owner + QUOTENAME(@dest_tabname) collate database_default + N' add constraint ' + QUOTENAME(@constraint_name) collate database_default + N' primary key clustered ('
  23315. insert into #proctext(procedure_text) values( @cmd )
  23316.  
  23317. select @spacer = N' '
  23318. select @cmd = N''
  23319.  
  23320. select @indkey = 1
  23321. while (@indkey <= 16)
  23322. begin    
  23323.     select @colname = index_col(@srcobj, @indid, @indkey)
  23324.     if (@colname is null)
  23325.     begin
  23326.         select @indkey = 16
  23327.     end
  23328.     else
  23329.     begin
  23330.         select @cmd = @cmd + @spacer + QUOTENAME(@colname) collate database_default
  23331.         select @spacer = N','
  23332.  
  23333.         if len( @cmd ) > 3000
  23334.         begin
  23335.             insert into #proctext(procedure_text) values( @cmd )
  23336.             select @cmd = N''
  23337.         end
  23338.     end
  23339.     select @indkey = @indkey + 1
  23340. end
  23341.  
  23342. insert into #proctext(procedure_text) values( @cmd )
  23343.  
  23344. insert into #proctext(procedure_text) values( N')' )
  23345.  
  23346. select procedure_text from #proctext order by c1 asc
  23347.  
  23348. go
  23349. EXEC dbo.sp_MS_marksystemobject sp_MSscriptmvastablepkc
  23350. GO
  23351.  
  23352. print ''
  23353. print 'Creating procedure sp_MSscriptmvastableidx'
  23354. go
  23355.  
  23356. create procedure sp_MSscriptmvastableidx @artid int
  23357. as
  23358. declare @cmd          nvarchar(4000)
  23359. declare @dest_owner   nvarchar(255)
  23360. declare @dest_tabname sysname
  23361. declare @src_objid    int
  23362. declare @constraint_name  sysname
  23363. declare @spacer          nvarchar(1)
  23364. declare @srcobj          nvarchar(1000)
  23365. declare @colname      sysname
  23366. declare @indkey          int
  23367. declare @indid          int
  23368.  
  23369. -------- create temp table for command fragments
  23370.  
  23371. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  23372.  
  23373. -------- get sysarticles information
  23374.  
  23375. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  23376.        @src_objid = objid
  23377. from sysarticles
  23378. where artid = @artid
  23379.  
  23380. if @dest_owner is not null
  23381. begin
  23382.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  23383. end
  23384. else
  23385. begin
  23386.     select @dest_owner = N''
  23387. end
  23388.  
  23389. select @srcobj = QUOTENAME( USER_NAME(OBJECTPROPERTY(@src_objid,'OwnerId'))) collate database_default + N'.' + QUOTENAME(object_name(@src_objid)) collate database_default
  23390.  
  23391. select @constraint_name = name, @indid = indid from sysindexes where id = @src_objid and status & 16 <> 0
  23392.  
  23393. select @cmd = N'create unique clustered index ' + QUOTENAME(@constraint_name) + N' on ' +@dest_owner + QUOTENAME(@dest_tabname) + N'('
  23394. insert into #proctext(procedure_text) values( @cmd )
  23395.  
  23396. select @spacer = N' '
  23397. select @cmd = N''
  23398.  
  23399. select @indkey = 1
  23400. while (@indkey <= 16)
  23401. begin    
  23402.     select @colname = index_col(@srcobj, @indid, @indkey)
  23403.     if (@colname is null)
  23404.     begin
  23405.         select @indkey = 16
  23406.     end
  23407.     else
  23408.     begin
  23409.         select @cmd = @cmd + @spacer + QUOTENAME(@colname)
  23410.         select @spacer = N','
  23411.  
  23412.         if len( @cmd ) > 3000
  23413.         begin
  23414.             insert into #proctext(procedure_text) values( @cmd )
  23415.             select @cmd = N''
  23416.         end
  23417.     end
  23418.     select @indkey = @indkey + 1
  23419. end
  23420.  
  23421. insert into #proctext(procedure_text) values( @cmd )
  23422.  
  23423. insert into #proctext(procedure_text) values( N')' )
  23424.  
  23425. select procedure_text from #proctext order by c1 asc
  23426.  
  23427. go
  23428. EXEC dbo.sp_MS_marksystemobject sp_MSscriptmvastableidx
  23429. GO
  23430.  
  23431.  
  23432. print ''
  23433. print 'Creating procedure sp_MSscriptmvastable'
  23434. go
  23435.  
  23436. create procedure sp_MSscriptmvastable @artid int
  23437. as
  23438. declare @cmd          nvarchar(4000)
  23439. declare @dest_owner   nvarchar(255)
  23440. declare @dest_tabname sysname
  23441. declare @src_objid    int
  23442. declare @artcolumns   binary(32)
  23443. declare @schema_option binary(8)
  23444. declare @art_col      int
  23445. declare @this_col      int
  23446. declare @isset          int
  23447. declare @use_base_type tinyint
  23448.  
  23449. declare @spacer          nvarchar(1)
  23450. declare @nullability  nvarchar(10)
  23451. declare @typestring   nvarchar(255)
  23452. declare @col_name      sysname
  23453.  
  23454. -------- create temp table for command fragments
  23455.  
  23456. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  23457.  
  23458. -------- get sysarticles information
  23459.  
  23460. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  23461.        @src_objid = objid, @artcolumns = columns, 
  23462.        @use_base_type = substring(schema_option,8,1) & 32
  23463. from sysarticles
  23464. where artid = @artid
  23465.  
  23466. if @dest_owner is not null
  23467. begin
  23468.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  23469. end
  23470. else
  23471. begin
  23472.     select @dest_owner = N''
  23473. end
  23474.  
  23475. -- script out CREATE TABLE statement
  23476.  
  23477. -- begin create table
  23478. select @cmd = N'create table ' + @dest_owner + QUOTENAME(@dest_tabname) + N'('
  23479. insert into #proctext(procedure_text) values( @cmd )
  23480.  
  23481. -- columns
  23482. select @art_col = 1
  23483. select @spacer = N' '
  23484.  
  23485. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  23486. select colid from syscolumns where id = @src_objid order by colid asc
  23487.  
  23488. OPEN hCColid
  23489.  
  23490. FETCH hCColid INTO @this_col
  23491.  
  23492. WHILE (@@fetch_status <> -1)
  23493. begin
  23494.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  23495.    select @col_name = name, 
  23496.           @nullability = case isnullable 
  23497.           when 0 then N'NOT NULL' 
  23498.           else N'NULL' end
  23499.           from syscolumns where id=@src_objid and @this_col=colid 
  23500.    if @isset != 0 and @col_name is not null
  23501.    begin
  23502.         if @use_base_type <> 0
  23503.         begin
  23504.             exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  23505.         end
  23506.         else
  23507.         begin
  23508.             exec dbo.sp_MSgettypestringudt @src_objid, @this_col, @typestring OUTPUT
  23509.         end
  23510.         select @cmd = @spacer + QUOTENAME(@col_name) + N' ' + @typestring + N' ' + @nullability 
  23511.         insert into #proctext(procedure_text) values( @cmd )
  23512.         select @art_col = @art_col + 1
  23513.         select @spacer = N','
  23514.    end
  23515.    FETCH hCColid INTO @this_col
  23516. end
  23517.  
  23518. CLOSE hCColid
  23519. DEALLOCATE hCColid
  23520.  
  23521. -- end create table
  23522. insert into #proctext(procedure_text) values( N')' )
  23523.  
  23524. select procedure_text from #proctext order by c1 asc
  23525. go
  23526. EXEC dbo.sp_MS_marksystemobject sp_MSscriptmvastable
  23527. GO
  23528.  
  23529. --------------------------------------------------------------------------
  23530. --------------------------------------------------------------------------
  23531.  
  23532. print ''
  23533. print 'Creating procedure sp_fetchshowcmdsinput'
  23534. go
  23535. SET ARITHABORT ON
  23536. SET NUMERIC_ROUNDABORT OFF
  23537. SET CONCAT_NULL_YIELDS_NULL ON
  23538. SET QUOTED_IDENTIFIER ON
  23539. SET ANSI_NULLS ON
  23540. SET ANSI_PADDING ON
  23541. SET ANSI_WARNINGS ON
  23542. go
  23543. create procedure sp_fetchshowcmdsinput @numcmds int
  23544. as
  23545. create table #rcmds( article_id int NOT NULL, partial_command int NOT NULL, command varbinary(1024) NULL, 
  23546. xactid binary(10) NOT NULL, xact_seqno binary(10) NOT NULL, publication_id int NOT NULL, 
  23547. command_id int NOT NULL, command_type int NOT NULL, originator_srvname nvarchar(128) collate database_default null, 
  23548. originator_db nvarchar(128) collate database_default null)
  23549. insert into #rcmds exec dbo.sp_replcmds @numcmds
  23550. 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
  23551. drop table #rcmds
  23552. go
  23553. SET ANSI_NULLS OFF
  23554. go
  23555. EXEC dbo.sp_MS_marksystemobject sp_fetchshowcmdsinput
  23556. GO
  23557.  
  23558. --------------------------------------------------------------------------
  23559. --------------------------------------------------------------------------
  23560.  
  23561. print ''
  23562. print 'Creating procedure sp_replshowcmds'
  23563. go
  23564.  
  23565. create procedure sp_replshowcmds @maxtrans int = 1
  23566. as
  23567. declare @query nvarchar(1024)
  23568. declare @dbname sysname
  23569. select @dbname = db_name()
  23570.  
  23571. select @query = 'execute dbo.sp_fetchshowcmdsinput ' + convert( nvarchar, @maxtrans )
  23572. execute master..xp_printstatements @query, @dbname
  23573. go
  23574.  
  23575. EXEC dbo.sp_MS_marksystemobject sp_replshowcmds
  23576. GO
  23577.  
  23578. print ''
  23579. print 'Creating procedure sp_article_validation'
  23580. go
  23581.  
  23582. create procedure sp_article_validation
  23583. @publication sysname,
  23584. @article sysname,
  23585. -- The following are values passed to the sp_table_validation call at the subscriber.
  23586. @rowcount_only smallint = 1,       
  23587. /* 
  23588. The @rowcount_only param is overloaded for shiloh release due to backward compatibility concerns.
  23589. In shiloh, the checksum functionality has changed.   So 7.0 subscribers will have the old checksum 
  23590. routines, which generate different CRC values, and do not have functionality for vertical partitions,
  23591. or logical table structures where column offsets differ (due to ALTER TABLEs that DROP and ADD columns).
  23592.  
  23593. In 7.0, this was a bit column.  0 meant do not do just a rowcount - do a checksum.  1 meant just do a 
  23594. rowcount.
  23595.  
  23596. For Shiloh, this parameter is changed to a smallint with these options:
  23597. 0 - Do a 7.0 compatible checksum
  23598. 1 - Do a rowcount check only
  23599. 2 - Use new Shiloh checksum functionality.  Note that because 7.0 subscribers will 
  23600. take this parameter as a bit type, not a smallint, it will be interpreted as simply
  23601. ON.  That means that passing a 2, and having a 7.0 subscriber, will result in the 7.0
  23602. subscriber doing only rowcount validation.   The Shiloh subscribers will do both
  23603. rowcount and checksum.  If you want 7.0 subscribers to do checksum validation, use 
  23604. the value of 0 for this parameter.   Shiloh subscribers can do the 7.0 compatible 
  23605. checksum, but that checksum has the same 7.0 limitations for vertical partitions 
  23606. and differences in physical table structure.)
  23607. */
  23608.               
  23609. @full_or_fast tinyint = 2,  -- full (value 0) does COUNT(*) 
  23610.                             -- fast (value 1) uses sysindexes.rows if table (not view); 
  23611.                             -- conditional fast (VALUE 2) , first tries fast method, but
  23612.                             -- reverts to full if fast method shows differences.
  23613. @shutdown_agent bit = 0,    -- If 1 will raise error 20578, which will signal subscriber synchronization agent to shutdown
  23614.                             -- immediately after successful validation
  23615. @subscription_level bit = 0        -- Whether or not the validation is only picked up by a set of subscribers
  23616.                                 -- that are specified by calls to sp_marksubscriptionvalidation.
  23617. , @reserved int = NULL            -- If not null, the sp is called from sp_publication_validation.
  23618. as
  23619.  
  23620. declare @publication_guid uniqueidentifier
  23621. declare @publication_id int
  23622. declare @article_guid uniqueidentifier
  23623. declare @article_id int
  23624. declare @source_name sysname
  23625. declare @source_owner sysname
  23626. declare @partition_view_id sysname, @table_id sysname
  23627. declare @sync_name sysname
  23628. declare @destination_table sysname
  23629. declare @destination_owner sysname
  23630. declare @columns varbinary(32) 
  23631. declare @command varchar (4096)
  23632. declare @retcode int
  23633. declare @actual_rowcount bigint
  23634. declare @actual_checksum numeric
  23635. declare @status int
  23636. declare @active int
  23637. declare @publish_bit int
  23638. declare @table_name sysname                    -- base table name var to passed to sp_table_validation
  23639.     , @allow_dts bit
  23640.     , @dts_part int
  23641.     
  23642. set nocount on
  23643.  
  23644.  
  23645. set @active = 1
  23646. set @publish_bit = 1
  23647. set @dts_part = 64
  23648.  
  23649. -- Check if the database is published for transactional
  23650. if not exists (select * from master..sysdatabases where name = db_name() collate database_default and (category & @publish_bit) = @publish_bit)
  23651. begin
  23652.     raiserror(20026, 16, -1, @publication)
  23653.     return 1
  23654. end
  23655.  
  23656. -- Get Publication Information
  23657. select @publication_id = pubid, @allow_dts = allow_dts from syspublications where name = @publication
  23658. if @publication_id is null
  23659. begin
  23660.     raiserror(20026, 16, -1, @publication)
  23661.     return 1
  23662. end
  23663.  
  23664. -- Get Article Information
  23665. select @article_id = artid, @sync_name = OBJECT_NAME(sync_objid),@partition_view_id=sync_objid,
  23666.     @destination_table = dest_table, @destination_owner = dest_owner, 
  23667.     @status = status, @table_name = OBJECT_NAME(objid),@table_id=objid,
  23668.     @columns = columns from sysarticles where name = @article and pubid=@publication_id
  23669.  
  23670. if @article_id is null
  23671. begin
  23672.     raiserror(20027, 16, -1, @article)
  23673.     return 1
  23674. end
  23675.  
  23676. -- Security check
  23677. -- Only people have 'select all' permission on the base table can do validation
  23678. if permissions(@table_id) & 1 <> 1
  23679. begin
  23680.     declare @qual_name nvarchar(512)
  23681.     exec dbo.sp_MSget_qualified_name @table_id, @qual_name output
  23682.     raiserror(20623, 16, -1, @article, @qual_name)
  23683.     return 1
  23684. end
  23685.  
  23686. -- Make sure article status is 'active' 
  23687. if (@status & @active) <> @active
  23688. begin
  23689.     -- Article is not active
  23690.     raiserror(20523, 16, -1, @article)
  23691.     return 1
  23692. end
  23693.  
  23694.  
  23695. if @allow_dts = 1
  23696. begin
  23697.     if @rowcount_only <> 1
  23698.     begin
  23699.         raiserror(20612, 16, -1)
  23700.         return (1) 
  23701.     end
  23702.     -- For dts horizontal partitioned article, no validation is possible, do nothing or
  23703.     -- raise error.
  23704.     if (@status & @dts_part <> 0)
  23705.     begin
  23706.         -- sp_article_validation is called directly, raise error and fail
  23707.         if @reserved is null
  23708.         begin
  23709.             raiserror(20613, 16, -1)
  23710.             return (1) 
  23711.         end
  23712.         -- sp_article_validation is called by sp_publication_validation, 
  23713.         -- raise warning and contiue.
  23714.         else
  23715.         begin
  23716.             raiserror(20613, 10, -1)
  23717.             return (0)
  23718.         end
  23719.     end
  23720. end
  23721.             
  23722.     
  23723.     
  23724.  
  23725. -- Check if table has vertical partition OR horizontal partition
  23726. if exists (select * from sysarticles a, syscolumns b
  23727.     where
  23728.     (
  23729.     -- horizontal partition    exists if filter column is not zero
  23730.     a.filter <> 0
  23731.     
  23732.     OR
  23733.     --vertical partition
  23734.      (CONVERT(bit, convert(binary(2), SUBSTRING(convert(nvarchar,a.columns), CONVERT(tinyint, 16 - FLOOR((colid-1)/16)), 1)) & POWER(2, ((colid-1)%16))) = 0
  23735.            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)
  23736.     )
  23737.            AND a.objid = b.id
  23738.            AND a.name = @article
  23739.            AND a.pubid = @publication_id)
  23740. begin
  23741.     set @source_name = @sync_name
  23742.     select @source_owner= user_name(uid) from sysobjects where id=@partition_view_id
  23743.  
  23744.     -- Partitions only support new shiloh checksum functionality or row count validation.
  23745.     -- If 7.0 compatible checksum was asked for (@rowcount_only=0), it will be changed to 
  23746.     -- override specified value, making it truly only check rowcounts.   If shiloh checksum 
  23747.     -- was asked for, thats ok (@rowcount_only=2), thats ok and no need to change it.
  23748.     if (@rowcount_only = 0)
  23749.         set @rowcount_only = 1
  23750. end
  23751.  
  23752. else
  23753.  
  23754. begin
  23755.       set @source_name = @table_name
  23756.     select @source_owner= user_name(uid) from sysobjects where id=@table_id
  23757.  
  23758. end
  23759.  
  23760.  
  23761. begin tran -- The table validation and posting to the log MUST happen with a transaction
  23762.  
  23763. -- Get publisher's rowcount and/or checksum for the article
  23764. if @rowcount_only = 1
  23765. begin
  23766.     exec @retcode = dbo.sp_table_validation @table = @source_name, @expected_rowcount = @actual_rowcount OUTPUT,
  23767.         @rowcount_only = 1, @owner=@source_owner, @full_or_fast = 0, @table_name = @table_name   -- always do full count at publisher
  23768.     if @retcode <> 0 or @@error <> 0 
  23769.     begin
  23770.         commit tran
  23771.         return 1
  23772.     end
  23773. end
  23774. else  -- get checksum
  23775. begin
  23776.     exec @retcode = dbo.sp_table_validation @table = @source_name, @expected_rowcount = @actual_rowcount OUTPUT,
  23777.         @expected_checksum = @actual_checksum OUTPUT, @rowcount_only = @rowcount_only, @owner=@source_owner,
  23778.         @full_or_fast = 0, @table_name = @table_name   -- always do full count at publisher
  23779.     if @retcode <> 0 or @@error <> 0 
  23780.     begin
  23781.         commit tran
  23782.         return 1
  23783.     end
  23784. end
  23785.  
  23786. -- Post sp_table_validation on behalf of the article and send to subscribers
  23787. if @rowcount_only = 1
  23788. begin
  23789.     select @command = 'exec dbo.sp_table_validation @table = ''' + @destination_table + ''', @expected_rowcount = ' +
  23790.         convert(varchar(10), @actual_rowcount) + ', @rowcount_only = 1' +
  23791.         ', @full_or_fast = ' + convert(varchar(10), @full_or_fast) +
  23792.         ', @shutdown_agent = ' + convert(varchar(10), @shutdown_agent)
  23793. end
  23794. else
  23795. begin
  23796.     select @command = 'exec dbo.sp_table_validation @table = ''' + @destination_table + ''', @expected_rowcount = ' +
  23797.         convert(varchar(10), @actual_rowcount) + ', @expected_checksum = ' + 
  23798.         convert(varchar(100), @actual_checksum) + ', @rowcount_only = ' + convert(varchar(5),@rowcount_only) +
  23799.         ', @full_or_fast = ' + convert(varchar(10), @full_or_fast) +
  23800.         ', @shutdown_agent = ' + convert(varchar(10), @shutdown_agent)
  23801. end 
  23802.  
  23803. -- Add owner param if destination owner is not NULL
  23804. if (@destination_owner IS NOT NULL)
  23805. begin
  23806.     select @command = @command +
  23807.     ', @owner = ''' + @destination_owner + ''''
  23808. end
  23809.  
  23810. declare @command_type int
  23811. if @subscription_level = 0
  23812.     select @command_type = 35 -- SQL Server Only command type
  23813. else
  23814.     select @command_type = 69 -- sub validation command
  23815.  
  23816. exec @retcode = dbo.sp_replpostcmd 
  23817.     0,              -- partial flag
  23818.     @publication_id, 
  23819.     @article_id, 
  23820.     @command_type,            -- SQL Server Only command type
  23821.     @command
  23822. if @retcode <> 0 or @@error <> 0
  23823. begin
  23824.     commit tran
  23825.     return 1
  23826. end
  23827.  
  23828. commit tran
  23829.  
  23830. Go
  23831.  
  23832. EXEC dbo.sp_MS_marksystemobject sp_article_validation
  23833.  
  23834. print ''
  23835. print 'Creating procedure sp_publication_validation'
  23836. go
  23837.  
  23838.  
  23839. create procedure sp_publication_validation
  23840. @publication sysname,
  23841. @rowcount_only smallint = 1,
  23842. /* 
  23843. The @rowcount_only param is overloaded for shiloh release due to backward compatibility concerns.
  23844. In shiloh, the checksum functionality has changed.   So 7.0 subscribers will have the old checksum 
  23845. routines, which generate different CRC values, and do not have functionality for vertical partitions,
  23846. or logical table structures where column offsets differ (due to ALTER TABLEs that DROP and ADD columns).
  23847.  
  23848. In 7.0, this was a bit column.  0 meant do not do just a rowcount - do a checksum.  1 meant just do a 
  23849. rowcount.
  23850.  
  23851. For Shiloh, this parameter is changed to a smallint with these options:
  23852. 0 - Do a 7.0 compatible checksum
  23853. 1 - Do a rowcount check only
  23854. 2 - Use new Shiloh checksum functionality.  Note that because 7.0 subscribers will 
  23855. take this parameter as a bit type, not a smallint, it will be interpreted as simply
  23856. ON.  That means that passing a 2, and having a 7.0 subscriber, will result in the 7.0
  23857. subscriber doing only rowcount validation.   The Shiloh subscribers will do both
  23858. rowcount and checksum.  If you want 7.0 subscribers to do checksum validation, use 
  23859. the value of 0 for this parameter.   Shiloh subscribers can do the 7.0 compatible 
  23860. checksum, but that checksum has the same 7.0 limitations for vertical partitions 
  23861. and differences in physical table structure.)
  23862. */
  23863.  
  23864. @full_or_fast tinyint = 2,  -- full (value 0) does COUNT(*) 
  23865.                             -- fast (value 1) uses sysindexes.rows if table (not view); 
  23866.                             -- conditional fast (VALUE 2) , first tries fast method, but
  23867.                             -- reverts to full if fast method shows differences.
  23868. @shutdown_agent bit = 0     -- Set for last article in publication, which will signal subscriber synchronization agent to shutdown
  23869.                             -- immediately after successful validation
  23870. as
  23871.  
  23872. set nocount on
  23873.  
  23874. declare @publication_id int
  23875. declare @article sysname
  23876. declare @article2 sysname
  23877. declare @retcode int
  23878. declare @publish_bit int
  23879.  
  23880.     
  23881. set @publish_bit = 1
  23882.  
  23883. -- Check if the database is published for transactional
  23884. if not exists (select * from master..sysdatabases where name = db_name() collate database_default and (category & @publish_bit) = @publish_bit)
  23885. begin
  23886.     raiserror(20026, 16, -1, @publication)
  23887.     return 1
  23888. end
  23889.  
  23890. -- Get Publication Information
  23891. select @publication_id = pubid from syspublications where name = @publication
  23892. if @publication_id is null
  23893. begin
  23894.     raiserror(20026, 16, -1, @publication)
  23895.     return 1
  23896. end
  23897.  
  23898. -- Security Check will be done inside sp_article_validation
  23899. -- Security check
  23900. -- Only people have 'select all' permission on the base table can do validation
  23901. declare @table_id int
  23902.  
  23903. select top 1 @article = name, @table_id = objid from sysarticles where
  23904.     pubid = @publication_id and 
  23905.     (status & 1) <> 0 and   -- active articles only
  23906.     (type & 1) <> 0 and        -- only checksum tables/views.
  23907.     ((permissions(objid) & 1) <> 1)
  23908.  
  23909. if @table_id is not null
  23910. begin
  23911.     declare @qual_name nvarchar(512)
  23912.     exec dbo.sp_MSget_qualified_name @table_id, @qual_name output
  23913.     raiserror(20623, 16, -1, @article, @qual_name)
  23914.     return 1
  23915. end
  23916.  
  23917. declare hC CURSOR LOCAL FAST_FORWARD for select name from sysarticles where pubid = @publication_id and
  23918. (status & 1) <> 0 and   -- active articles only
  23919. (type & 1) <> 0            -- only checksum tables/views.
  23920.  
  23921. open hC
  23922. fetch hC into @article
  23923. while (@@fetch_status <> -1)
  23924. begin
  23925.     set @article2 = @article
  23926.  
  23927.     -- Look ahead to next article
  23928.     fetch hC into @article
  23929.  
  23930.     -- If we are at the last article, pass the @shutdown_agent value
  23931.     if (@@fetch_status = -1) 
  23932.     begin
  23933.         exec @retcode = dbo.sp_article_validation @publication, @article2, @rowcount_only = @rowcount_only,
  23934.             @full_or_fast = @full_or_fast, @shutdown_agent = @shutdown_agent, @reserved = 1
  23935.  
  23936.     end
  23937.     else
  23938.         exec @retcode = dbo.sp_article_validation @publication, @article2, @rowcount_only = @rowcount_only,
  23939.             @full_or_fast = @full_or_fast, @reserved = 1
  23940.     
  23941.     if @retcode <> 0 or @@error <> 0
  23942.     begin
  23943.         close hC
  23944.         deallocate hC
  23945.         return 1
  23946.     end
  23947. end
  23948. close hC
  23949. deallocate hC
  23950. go
  23951.  
  23952. EXEC dbo.sp_MS_marksystemobject sp_publication_validation
  23953. GO
  23954.  
  23955.  
  23956. print ''
  23957. print 'Creating procedure sp_marksubscriptionvalidation'
  23958. go
  23959.  
  23960.  
  23961. CREATE PROCEDURE sp_marksubscriptionvalidation (
  23962.     @publication sysname,    /* publication name */
  23963.     @subscriber sysname,             /* subscriber name */
  23964.     @destination_db sysname   /* destination database name */
  23965. ) AS
  23966.  
  23967.     DECLARE @retcode int, @pubid int
  23968.  
  23969.     DECLARE @artid int, @active tinyint
  23970.     DECLARE @srvid smallint
  23971.     DECLARE @non_sql_flag bit
  23972.  
  23973.   
  23974.     -- Initialization
  23975.     select @active = 2
  23976.  
  23977.     /* 
  23978.     ** Security Check.
  23979.     */
  23980.     exec @retcode = dbo.sp_MSreplcheck_publish
  23981.     if @@ERROR <> 0 or @retcode <> 0
  23982.         return(1)
  23983.  
  23984.     /* Validate names */
  23985.  
  23986.     EXECUTE @retcode = dbo.sp_validname @publication
  23987.     IF @@ERROR <> 0 OR @retcode <> 0
  23988.         RETURN (1)
  23989.  
  23990.     EXECUTE @retcode = dbo.sp_validname @subscriber
  23991.     IF @@ERROR <> 0 OR @retcode <> 0
  23992.         RETURN (1)
  23993.  
  23994.     EXECUTE @retcode = dbo.sp_validname @destination_db
  23995.     IF @@ERROR <> 0 OR @retcode <> 0
  23996.         RETURN (1)
  23997.  
  23998.     /*
  23999.     ** Parameter Check:  @publication
  24000.     ** Check to make sure that the publication exists, that it's not NULL,
  24001.     ** and that it conforms to the rules for identifiers.
  24002.     */
  24003.     SELECT @pubid = pubid FROM syspublications WHERE name = @publication
  24004.     if @pubid is null
  24005.     begin
  24006.         RAISERROR (20026, 16, -1, @publication)
  24007.         RETURN (1)
  24008.     END
  24009.  
  24010.     /*
  24011.     ** Parameter Check:  @subscriber
  24012.     ** Check to make sure that the subscriber exists
  24013.     */
  24014.     select @subscriber = UPPER(@subscriber)
  24015.         
  24016.     SELECT @srvid = srvid, @non_sql_flag = 
  24017.         case when srvproduct = N'MSREPL-NONSQL' then 1
  24018.         else 0 end
  24019.         FROM master..sysservers
  24020.         WHERE UPPER(srvname) = UPPER(@subscriber) collate database_default
  24021.           AND (srvstatus & 4) <> 0
  24022.     if @srvid is null
  24023.     BEGIN
  24024.         RAISERROR (14063, 16, -1)
  24025.         RETURN (1)
  24026.     END
  24027.  
  24028.     if @non_sql_flag = 1
  24029.     begin
  24030.         RAISERROR (20614, 16, -1)
  24031.         RETURN (1)
  24032.     end
  24033.  
  24034.     -- Wrong dest_db will be caught by the following query
  24035.  
  24036.     -- Check to make sure the subscription exists 
  24037.     IF NOT EXISTS (SELECT *
  24038.           FROM syssubscriptions sub,
  24039.                sysextendedarticlesview art,
  24040.                syspublications pub
  24041.          WHERE pub.pubid = @pubid
  24042.            AND sub.srvid = @srvid
  24043.            AND sub.artid = art.artid
  24044.            AND art.pubid = pub.pubid
  24045.            AND sub.dest_db = @destination_db)
  24046.     BEGIN
  24047.         RAISERROR (14055, 16, -1)
  24048.         RETURN (1)
  24049.     END
  24050.  
  24051.     -- Select an article for that is actively subscribed.
  24052.     -- If none is found, do nothing
  24053.     select top 1 @artid = art.artid 
  24054.           FROM syssubscriptions sub,
  24055.                sysextendedarticlesview art
  24056.          WHERE sub.srvid = @srvid
  24057.            AND sub.artid = art.artid
  24058.            AND art.pubid = @pubid
  24059.            AND sub.dest_db = @destination_db
  24060.            AND sub.status = @active
  24061.  
  24062.     if @artid is null
  24063.         return 0
  24064.  
  24065.     declare @command nvarchar (1000)
  24066.  
  24067.     -- No need to quote them
  24068.     select @command = @subscriber + @destination_db
  24069.     exec @retcode = dbo.sp_replpostcmd 
  24070.         0,              -- partial flag
  24071.         @pubid, 
  24072.         @artid, 
  24073.         68,             -- subscription validation marker
  24074.         @command
  24075.     if @retcode <> 0 or @@error <> 0
  24076.         return 1
  24077.  
  24078.     RETURN(0)
  24079. go
  24080.  
  24081. EXEC dbo.sp_MS_marksystemobject sp_marksubscriptionvalidation
  24082. GO
  24083.  
  24084. print ''
  24085. print 'Creating procedure sp_dropanonymousagent'
  24086. go
  24087.  
  24088.  
  24089. CREATE PROCEDURE sp_dropanonymousagent
  24090. @subid uniqueidentifier,
  24091. @type int -- 1 tran sub, 2 merge sub
  24092. as
  24093.     set nocount on 
  24094.     declare @login sysname
  24095.     -- Null @login indicates sysadmin or db_owner
  24096.     if IS_SRVROLEMEMBER ('sysadmin') = 0 and is_member('db_owner') = 0
  24097.         select @login = suser_sname()
  24098.     /*
  24099.     ** Get distribution server information for remote RPC
  24100.     ** agent verification.
  24101.     */
  24102.     declare @distributor sysname
  24103.     declare @distribdb sysname
  24104.     declare @distproc nvarchar(1000)
  24105.     declare @retcode int
  24106.  
  24107.     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  24108.         @distribdb = @distribdb OUTPUT
  24109.  
  24110.     IF @@error <> 0 OR @retcode <> 0
  24111.     BEGIN
  24112.         RAISERROR (14071, 16, -1)
  24113.         RETURN (1)
  24114.     END
  24115.  
  24116.     /*
  24117.     ** Call proc to change the distributor
  24118.     */
  24119.     SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  24120.         '.dbo.sp_MSdrop_anonymous_entry'
  24121.  
  24122.     exec @retcode = @distproc 
  24123.         @subid = @subid,
  24124.         @login = @login,
  24125.         @type = @type
  24126.  
  24127.     IF @@error <> 0 OR @retcode <> 0
  24128.         RETURN (1)
  24129.  
  24130.     RETURN (0)
  24131. go
  24132.  
  24133. EXEC dbo.sp_MS_marksystemobject sp_dropanonymousagent
  24134. GO
  24135.  
  24136. print ''
  24137. print 'Creating procedure sp_replrestart'
  24138. go
  24139.  
  24140.  
  24141. CREATE PROCEDURE sp_replrestart 
  24142. AS
  24143.  
  24144.     SET NOCOUNT ON
  24145.  
  24146.     /*
  24147.     ** Declarations.
  24148.     */
  24149.     declare @retcode int
  24150.         ,@lsn binary(10)
  24151.         ,@dist_lsn binary(10)
  24152.         ,@distributor sysname
  24153.         ,@distribdb sysname
  24154.         ,@distproc nvarchar(4000)
  24155.         ,@dbname sysname
  24156.     /*
  24157.     ** Initializations
  24158.     */
  24159.     select @retcode = 0
  24160.     select @dbname = db_name()
  24161.  
  24162.     /*
  24163.     ** Security
  24164.     */
  24165.     exec @retcode = dbo.sp_MSreplcheck_publish
  24166.     if @@ERROR <> 0 or @retcode <> 0
  24167.         return(1)
  24168.  
  24169.     -- Make sure the database is published.
  24170.     IF (SELECT category & 1
  24171.           FROM master..sysdatabases
  24172.          WHERE name = @dbname collate database_default) = 0
  24173.     BEGIN
  24174.         RAISERROR (14013, 16, -1)
  24175.         RETURN (1)
  24176.     END
  24177.  
  24178.     -- Make sure that the log reader is not running
  24179.     -- Use 0 so that it will not hold the repl proc structure (the lock).
  24180.     exec @retcode = dbo.sp_replcmds 0
  24181.     if @@ERROR <> 0 or @retcode <> 0
  24182.     begin
  24183.         RAISERROR (20610, 16, -1, 'sp_replrestart')
  24184.         return(1)
  24185.     end
  24186.  
  24187.     /*
  24188.     ** Get distribution server information for remote RPC call.
  24189.     */
  24190.  
  24191.     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  24192.                                        @distribdb = @distribdb OUTPUT
  24193.  
  24194.     IF @@ERROR <> 0 OR  @retcode <> 0
  24195.     BEGIN
  24196.         RAISERROR (14071, 16, -1)
  24197.         RETURN (1)
  24198.     END
  24199.  
  24200.     -- Get max dist lsn
  24201.     SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + '.dbo.sp_MSget_last_transaction'
  24202.     EXECUTE @retcode = @distproc 
  24203.         @publisher = @@SERVERNAME,
  24204.         @publisher_db = @dbname,
  24205.         @max_xact_seqno = @dist_lsn output
  24206.     IF @@ERROR <> 0 or @retcode <> 0
  24207.         return -1
  24208.  
  24209.     if @dist_lsn is null
  24210.         set @dist_lsn = 0x0
  24211.  
  24212.     -- To safeguard the case when the logreader is started after the check later
  24213.     -- use a tran to prevent the logreader from picking up the new lsns
  24214.     begin tran
  24215.  
  24216.     while 1 = 1
  24217.     begin
  24218.         -- Get publisher's lsn
  24219.         EXEC @retcode = dbo.sp_replincrementlsn @lsn OUTPUT
  24220.         IF @@ERROR <> 0 or @retcode <> 0
  24221.             goto UNDO
  24222.  
  24223.         if @lsn > @dist_lsn
  24224.             break
  24225.     end
  24226.  
  24227.     /* Mark the new starting point of the replication.*/
  24228.     exec @retcode = dbo.sp_repldone NULL, NULL, 0, 0, 1
  24229.     IF @@ERROR <> 0 or @retcode <> 0
  24230.         GOTO UNDO
  24231.  
  24232.     /* release our hold on the db as logreader */
  24233.     EXEC @retcode = dbo.sp_replflush
  24234.     IF @@ERROR <> 0 or @retcode <> 0
  24235.         GOTO UNDO
  24236.  
  24237.     commit tran
  24238.     return 0
  24239.  
  24240. UNDO:
  24241.     if @@trancount <> 0
  24242.         rollback tran
  24243. go
  24244.  
  24245. EXEC dbo.sp_MS_marksystemobject sp_replrestart
  24246. GO
  24247.  
  24248.  
  24249. print ''
  24250. print 'Creating procedure sp_MSpub_adjust_identity'
  24251. go
  24252.  
  24253. CREATE PROCEDURE sp_MSpub_adjust_identity
  24254. @artid int = null
  24255. as
  24256.     set nocount on
  24257.  
  24258.     declare @retcode int
  24259.     declare @cmd nvarchar(1000)
  24260.     declare @objid int, @threshhold int
  24261.     declare @pub_range bigint, @next_seed bigint, @current_pub_range bigint
  24262.     declare    @last_seed bigint, @identity_so_far bigint, @threshold int, @range bigint
  24263.     declare @database sysname, @table_name sysname
  24264.     declare @qualname nvarchar(512)
  24265.     DECLARE @distributor sysname
  24266.     DECLARE @distribdb sysname
  24267.  
  24268.     /*
  24269.     ** Security Check.
  24270.     */
  24271.     exec @retcode = dbo.sp_MSreplcheck_publish
  24272.     if @@ERROR <> 0 or @retcode <> 0
  24273.         return(1)
  24274.     
  24275.     select @database = db_name()
  24276.  
  24277.     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  24278.                                        @distribdb = @distribdb OUTPUT
  24279.     IF @@ERROR <> 0
  24280.     BEGIN
  24281.         RAISERROR (14071, 16, -1)
  24282.         RETURN (1)
  24283.     END
  24284.  
  24285.     DECLARE adjust_identity CURSOR LOCAL FAST_FORWARD FOR
  24286.         SELECT art1.objid
  24287.           FROM sysarticles art1,
  24288.                sysarticleupdates art2
  24289.           where art1.artid = art2.artid and
  24290.                 art2.identity_support = 1 and
  24291.                 (art1.artid = @artid or @artid is null)
  24292.     FOR READ ONLY
  24293.  
  24294.     OPEN adjust_identity        
  24295.     FETCH adjust_identity INTO @objid
  24296.     WHILE (@@fetch_status <> -1)
  24297.     begin
  24298.         select @table_name = object_name(@objid)
  24299.         exec @retcode = dbo.sp_MSget_qualified_name @objid, @qualname OUTPUT
  24300.         
  24301.         select @range = range, @pub_range = pub_range, @current_pub_range = current_pub_range, 
  24302.             @last_seed = last_seed, 
  24303.             @threshold = threshold from 
  24304.             MSpub_identity_range where objid=@objid
  24305.   
  24306.         select @identity_so_far = ident_current(@qualname)
  24307.  
  24308.         if @last_seed is null
  24309.         begin
  24310.             -- First time
  24311.             select @last_seed = (@identity_so_far / @pub_range) * @pub_range
  24312.             -- We always reserve a new range for the publisher without reseeding 
  24313.             -- the publisher, and we guarantee to have more slots then 
  24314.             -- a full range initially for the publisher.
  24315.             if    (@pub_range > 0 and @last_seed < @identity_so_far) or
  24316.                 (@pub_range < 0 and @last_seed > @identity_so_far)
  24317.                 select @last_seed = @last_seed + @pub_range
  24318.  
  24319.             select @next_seed = @last_seed + @pub_range
  24320.             -- Initialize distribution side entry
  24321.             SELECT @cmd = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSinsert_identity'
  24322.             EXEC @retcode = @cmd
  24323.                 @publisher = @@servername,
  24324.                 @publisher_db = @database,
  24325.                 @tablename = @table_name,
  24326.                 @identity_support = 1,
  24327.                 @pub_identity_range = 0, -- We don't need this at the distributor
  24328.                 @identity_range = @range,
  24329.                 @threshold     = @threshold,
  24330.                 -- Make sure we don't have gap at the beginning
  24331.                 @next_seed    = @next_seed,
  24332.                 @max_identity = null
  24333.             IF @@ERROR <> 0 OR @retcode <> 0
  24334.                 GOTO UNDO
  24335.             -- Add constraint only without reseeding.
  24336.             exec @retcode = dbo.sp_MSreseed
  24337.                 @objid = @objid,
  24338.                 @next_seed = @last_seed,
  24339.                 @range = @pub_range,
  24340.                 @is_publisher = -1,
  24341.                 @check_only = 1,
  24342.                 @initial_setting = 1,
  24343.                 @bound_value = @identity_so_far
  24344.  
  24345.             IF @@ERROR <> 0 OR @retcode <> 0
  24346.                 GOTO UNDO
  24347.             update MSpub_identity_range set last_seed = @last_seed where objid = @objid
  24348.             IF @@ERROR <> 0
  24349.                 GOTO UNDO
  24350.         end
  24351.         else
  24352.         begin
  24353.  
  24354.             -- Leave one slot unused. This is to prevent violation of primary key constraint
  24355.             -- if the next value is used by a subscriber and the publisher has received it.
  24356.             -- It seems the pk constraint will be validated before this check.
  24357.             declare @actual_range int
  24358.             if @current_pub_range > 0
  24359.                 select @actual_range = @current_pub_range -1
  24360.             else
  24361.                 select @actual_range = @current_pub_range +1
  24362.  
  24363.             -- Calculate the current ratio
  24364.             if 100*(@identity_so_far - @last_seed)/@actual_range >= @threshold
  24365.             -- need bump up
  24366.             begin
  24367.                 SELECT @cmd = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSfetchAdjustidentityrange'
  24368.                 EXEC @retcode = @cmd
  24369.                     @publisher = @@servername,
  24370.                     @publisher_db = @database,
  24371.                     @tablename = @table_name,
  24372.                     @adjust_only = 1,
  24373.                     @for_publisher = 1,
  24374.                     @range = @pub_range,
  24375.                     @next_seed = @next_seed output
  24376.                 IF @@ERROR <> 0 OR @retcode <> 0
  24377.                     GOTO UNDO
  24378.  
  24379.                 select @last_seed = @next_seed - @pub_range
  24380.                 
  24381.                 update MSpub_identity_range set last_seed = @last_seed,
  24382.                     current_pub_range = @pub_range
  24383.                     where objid = @objid
  24384.                 IF @@ERROR <> 0
  24385.                     GOTO UNDO
  24386.                 -- RESEED and change constraint
  24387.                 exec @retcode = dbo.sp_MSreseed
  24388.                     @objid = @objid,
  24389.                     @next_seed = @last_seed,
  24390.                     @range = @pub_range,
  24391.                     @is_publisher = -1
  24392.                 IF @@ERROR <> 0 OR @retcode <> 0
  24393.                     GOTO UNDO
  24394.             end
  24395.         end
  24396.  
  24397.         FETCH adjust_identity INTO @objid
  24398.     end
  24399.     return 0
  24400. UNDO:
  24401.     -- No need to start a transaction.
  24402.     return 1
  24403. go
  24404.  
  24405. EXEC dbo.sp_MS_marksystemobject sp_MSpub_adjust_identity
  24406. GO
  24407.  
  24408.  
  24409. print ''
  24410. print 'Creating procedure sp_helparticledts'
  24411. go
  24412.  
  24413. CREATE PROCEDURE sp_helparticledts (
  24414.     @publication sysname,        /* Publication name */
  24415.     @article sysname             /* Article name */
  24416.     ) AS
  24417.  
  24418.     SET NOCOUNT ON
  24419.  
  24420.     /*
  24421.     ** Declarations.
  24422.     */
  24423.  
  24424.     DECLARE @artid int
  24425.     DECLARE @pubid int
  24426.     DECLARE @retcode int
  24427.     declare @article_name sysname
  24428.  
  24429.    /*
  24430.     ** Check to see if the database has been activated for publication.
  24431.     */
  24432.  
  24433.     IF (SELECT category & 1
  24434.           FROM master..sysdatabases
  24435.          WHERE name = DB_NAME() collate database_default) = 0
  24436.  
  24437.     BEGIN
  24438.             RAISERROR (14013, 16, -1)
  24439.             RETURN (1)
  24440.     END
  24441.  
  24442.  
  24443.     /*
  24444.     ** Parameter Check:  @publication.
  24445.     ** Make sure that the publication exists.
  24446.     */
  24447.  
  24448.     IF @publication IS NULL
  24449.         BEGIN
  24450.             RAISERROR (14043, 16, -1, '@publication')
  24451.             RETURN (1)
  24452.         END
  24453.  
  24454.     EXECUTE @retcode = dbo.sp_validname @publication
  24455.  
  24456.     IF @@ERROR <> 0 OR @retcode <> 0
  24457.     RETURN (1)
  24458.  
  24459.     declare @allow_dts bit
  24460.  
  24461.     SELECT @pubid = pubid, @allow_dts = allow_dts    
  24462.         FROM syspublications WHERE name = @publication
  24463.  
  24464.     IF @pubid IS NULL
  24465.         BEGIN
  24466.             RAISERROR (20026, 11, -1, @publication)
  24467.             RETURN (1)
  24468.         END
  24469.  
  24470.  
  24471.     if @allow_dts = 0
  24472.     begin
  24473.         RAISERROR ('The publication ''%s'' does not allow DTS.', 11, -1, @publication)
  24474.         RETURN (1)
  24475.     end
  24476.  
  24477.     /*
  24478.     ** Check to see that the article exists in sysarticles.
  24479.     ** Fetch the article identification number.
  24480.     */
  24481.  
  24482.     IF @article IS NULL
  24483.         BEGIN
  24484.             RAISERROR (14043, 16, -1, '@article')
  24485.             RETURN (1)
  24486.         END
  24487.  
  24488.     /*
  24489.     EXECUTE @retcode = dbo.sp_validname @article
  24490.  
  24491.     IF @retcode <> 0
  24492.     RETURN (1)
  24493.     */
  24494.  
  24495.     SELECT @artid = artid, @article_name = name
  24496.       FROM sysarticles
  24497.      WHERE name = @article
  24498.        AND pubid = @pubid
  24499.     IF @artid IS NULL
  24500.         BEGIN
  24501.             RAISERROR (20027, 11, -1, @article)
  24502.             RETURN (1)
  24503.         END
  24504.     
  24505.     select 
  24506.         N'pre_script_ignore_error_task_name' = @article_name + N'_pre_ignore_error',
  24507.         N'pre_script_task_name' = @article_name + N'_pre',
  24508.         N'transformation_task_name' = @article_name,
  24509.         N'post_script_ignore_error_task_name' = @article_name + N'_post_ignore_error',
  24510.         N'post_script_task_name' = @article_name + N'_post'
  24511. go
  24512.  
  24513. EXEC dbo.sp_MS_marksystemobject sp_helparticledts
  24514. GO
  24515.  
  24516.  
  24517. print ''
  24518. print 'Creating procedure sp_changesubscriptiondtsinfo'
  24519. go
  24520.  
  24521. CREATE PROCEDURE sp_changesubscriptiondtsinfo (
  24522.     @job_id varbinary(16),
  24523.     @dts_package_name sysname = NULL,
  24524.     @dts_package_password sysname = NULL,
  24525.     @dts_package_location nvarchar(12) = NULL
  24526.  
  24527.     ) AS
  24528.  
  24529.     /*
  24530.     ** Declarations.
  24531.     */
  24532.  
  24533.     DECLARE @srvid smallint
  24534.     DECLARE @artid int
  24535.     DECLARE @retcode int
  24536.     declare @login_name sysname
  24537.     declare @update_mode int
  24538.     declare @subscription_type int
  24539.     declare @dts_package_location_id int
  24540.  
  24541.     /*
  24542.     ** Initializations.
  24543.     */
  24544.     SET NOCOUNT ON
  24545.     
  24546.     
  24547.     /* 
  24548.     ** Get subscription properties and do Security Check.
  24549.     ** We use login_name stored in syssubscriptions to manage security 
  24550.     */
  24551.  
  24552.     select @update_mode = update_mode, @login_name = login_name,
  24553.         @subscription_type = subscription_type,
  24554.         @artid = artid              
  24555.         FROM syssubscriptions s WHERE 
  24556.             s.distribution_jobid = @job_id
  24557.  
  24558.     /*
  24559.     ** Check if the subscription exists.
  24560.     */
  24561.     IF @update_mode is null
  24562.     BEGIN
  24563.         RAISERROR (14055, 11, -1)
  24564.         RETURN (1)
  24565.     END
  24566.  
  24567.     if    @update_mode != 0
  24568.     begin
  24569.         RAISERROR(21180, 16, -1)    
  24570.         RETURN (1)
  24571.     end
  24572.  
  24573.     -- Only push store DTS info at distributor.
  24574.     if @subscription_type <> 0
  24575.     begin
  24576.         RAISERROR(21181, 16, -1)    
  24577.         RETURN (1)
  24578.     end
  24579.  
  24580.     --Security check
  24581.  
  24582.     IF  suser_sname(suser_sid()) <> @login_name AND is_srvrolemember('sysadmin') <> 1  
  24583.         AND is_member ('db_owner') <> 1
  24584.     BEGIN
  24585.         -- Only members of the sysadmin fixed server role, db_owner fixed database role or the creator of the subscription can change this subscription property.'
  24586.         RAISERROR(21175, 11, -1)
  24587.         RETURN (1)
  24588.     END
  24589.  
  24590.     -- Get pubid
  24591.     declare @pubid int
  24592.     select @pubid = pubid from sysarticles where artid = @artid
  24593.  
  24594.     /* Get subscription type of the publication */
  24595.     if not exists (select * from syspublications where
  24596.         pubid = @pubid and
  24597.         allow_dts = 1)
  24598.     begin
  24599.         RAISERROR(21178, 16, -1)    
  24600.         RETURN (1)
  24601.     end
  24602.  
  24603.     if @dts_package_location is null
  24604.         select @dts_package_location_id = null
  24605.     else IF LOWER(@dts_package_location collate SQL_Latin1_General_CP1_CS_AS) = N'distributor' 
  24606.         select @dts_package_location_id = 0
  24607.     ELSE IF LOWER(@dts_package_location collate SQL_Latin1_General_CP1_CS_AS) = N'subscriber' 
  24608.         select @dts_package_location_id = 1
  24609.     ELSE 
  24610.     begin
  24611.         raiserror(20587, 16, -1, '@dts_package_location', 'sp_changesubscriptiondtsinfo')
  24612.         return(1)
  24613.     end
  24614.  
  24615.     -- Encrypt DTS package password
  24616.     declare @change_password bit
  24617.  
  24618.     if @dts_package_password is null
  24619.         select @change_password = 0
  24620.     else
  24621.         select @change_password = 1
  24622.  
  24623.     -- When user sends in empty string, reset it to null.
  24624.     -- Have to do this before scramble because the result may contains invalid
  24625.     -- unicode code points which are equael to some collation.
  24626.     if @dts_package_password = N''
  24627.         select @dts_package_password = NULL
  24628.  
  24629.     declare @enc_dts_package_password nvarchar(524)
  24630.         select @enc_dts_package_password = @dts_package_password
  24631.  
  24632.     if @enc_dts_package_password is not null
  24633.     begin
  24634.         EXEC @retcode = master.dbo.xp_repl_encrypt @enc_dts_package_password OUTPUT
  24635.         IF @@error <> 0 OR @retcode <> 0
  24636.             return 1
  24637.     end
  24638.  
  24639.     /*
  24640.     ** Get distribution server information for remote RPC
  24641.     ** agent verification.
  24642.     */
  24643.     declare @distributor sysname
  24644.     declare @distribdb sysname
  24645.     declare @distproc nvarchar(1000)
  24646.  
  24647.     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  24648.         @distribdb = @distribdb OUTPUT
  24649.  
  24650.     IF @@error <> 0 OR @retcode <> 0
  24651.     BEGIN
  24652.         RAISERROR (14071, 16, -1)
  24653.         RETURN (1)
  24654.     END
  24655.  
  24656.     /*
  24657.     ** Call proc to change the distributor
  24658.     */
  24659.     SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  24660.         '.dbo.sp_MSchange_subscription_dts_info'
  24661.  
  24662.     exec @retcode = @distproc 
  24663.         @job_id = @job_id,
  24664.         @dts_package_name = @dts_package_name,
  24665.         @dts_package_password = @enc_dts_package_password,
  24666.         @dts_package_location = @dts_package_location_id,
  24667.         @change_password = @change_password
  24668.  
  24669.     IF @@error <> 0 OR @retcode <> 0
  24670.         RETURN (1)
  24671.  
  24672.     RETURN (0)
  24673. go
  24674.  
  24675. EXEC dbo.sp_MS_marksystemobject sp_changesubscriptiondtsinfo
  24676. GO
  24677.  
  24678. print ''
  24679. print 'Creating procedure sp_MSdrop_6x_replication_agent'
  24680. go
  24681. create procedure sp_MSdrop_6x_replication_agent
  24682. @job_id UNIQUEIDENTIFIER,
  24683. @category_id int
  24684. as
  24685.     declare @distbit int
  24686.     declare @db_name sysname
  24687.     declare @cmd varchar(4000)
  24688.  
  24689.     select @distbit = 16
  24690.  
  24691.     declare hCdatabase CURSOR LOCAL FAST_FORWARD FOR
  24692.         select name from master.dbo.sysdatabases 
  24693.             where
  24694.             category & @distbit <> 0 
  24695.         for read only
  24696.  
  24697.     open hCdatabase
  24698.     fetch next from hCdatabase into @db_name
  24699.     while (@@fetch_status <> -1)
  24700.     begin
  24701.  
  24702.         if @category_id = 13
  24703.         begin
  24704.             select @cmd = 'delete from ' + @db_name + '.dbo.MSlogreader_agents where job_id = convert (uniqueidentifier, ''' +
  24705.                 convert (varchar(100), @job_id) + ''')'
  24706.             exec (@cmd)
  24707.         end
  24708.         else if @category_id = 15   
  24709.         begin
  24710.             select @cmd = @db_name + '.dbo.sp_MSdrop_6x_publication'
  24711.             exec @cmd @job_id = @job_id
  24712.         end
  24713.         else
  24714.             return 0
  24715.  
  24716.         if @@ERROR <> 0
  24717.             return 1
  24718.         
  24719.         fetch next from hCdatabase into @db_name
  24720.     end
  24721.     close hCdatabase
  24722.     deallocate hCdatabase
  24723. go
  24724.  
  24725. EXEC dbo.sp_MS_marksystemobject sp_MSdrop_6x_replication_agent
  24726. GO
  24727.  
  24728. print ''
  24729. print 'Creating procedure sp_MSreinit_article'
  24730. go
  24731. create procedure sp_MSreinit_article (
  24732.     @publication sysname
  24733.     ,@article sysname = N'%'
  24734.     ,@need_new_snapshot bit = 0
  24735.     ,@need_reinit_subscription bit = 0
  24736.     ,@force_invalidate_snapshot bit    = 0
  24737.     ,@force_reinit_subscription bit = 0
  24738.     ,@check_only bit = 0
  24739. )
  24740. as
  24741.     declare @retcode int
  24742.         ,@active tinyint
  24743.         ,@subscribed tinyint
  24744.         ,@artid int
  24745.         ,@pubid int
  24746.         ,@none tinyint
  24747.         ,@immediate_sync_ready bit
  24748.         ,@allow_anonymous bit
  24749.  
  24750.     -- Initialization
  24751.     select @active = 2
  24752.     select @subscribed = 1
  24753.     SELECT @none = 2            /* Const: synchronization type 'none' */
  24754.     select @active = 2
  24755.     select @pubid = pubid, @immediate_sync_ready = immediate_sync_ready,
  24756.         @allow_anonymous = allow_anonymous 
  24757.         from syspublications where name = @publication
  24758.     
  24759.     if @article = N'%'
  24760.         select @artid = 0
  24761.     else
  24762.         select @artid = artid from sysarticles where name = @article and pubid = @pubid
  24763.  
  24764.     begin tran 
  24765.     save tran sp_MSreinit_article
  24766.  
  24767.     if @need_new_snapshot = 1 and @immediate_sync_ready = 1
  24768.     begin
  24769.         -- If at publication level, we know that we should do it since 
  24770.         -- @immediate_sync_ready = 1
  24771.         -- If at article level, we only do it for the articles that have been
  24772.         -- processed by the snapshot agent, but not new articles.
  24773.         -- sp_addarticle calls this proc at publication level.
  24774.         -- It also make calls to sp_articlecolumn and sp_articleview which in turn
  24775.         -- call this sp. We don't want to do anything here with those calls.
  24776.         if @artid = 0 or exists (select * from syssubscriptions s where 
  24777.             s.srvid < 0 and
  24778.             s.status = @active and
  24779.             s.artid = @artid)
  24780.         begin
  24781.             -- Fail and raiserror error
  24782.             if @force_invalidate_snapshot = 0
  24783.             begin
  24784.                 raiserror(20607, 16, -1)
  24785.                 goto UNDO
  24786.             end
  24787.  
  24788.             if @check_only = 0
  24789.             begin
  24790.                 UPDATE syspublications SET immediate_sync_ready = 0 WHERE 
  24791.                     pubid = @pubid and
  24792.                     immediate_sync_ready <> 0
  24793.                 IF @@ERROR <> 0
  24794.                     goto UNDO
  24795.  
  24796.                 DECLARE @distributor sysname
  24797.                     , @distribdb sysname
  24798.                     , @distproc nvarchar (255)
  24799.                     , @dbname sysname
  24800.  
  24801.                 select @dbname = db_name()
  24802.  
  24803.                 EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  24804.                                                    @distribdb = @distribdb OUTPUT
  24805.                 IF @retcode <> 0 OR @@ERROR <> 0
  24806.                     goto UNDO
  24807.  
  24808.                 IF @distribdb IS NULL OR @distributor IS NULL
  24809.                 BEGIN
  24810.                     RAISERROR (14071, 16, -1)
  24811.                     goto UNDO
  24812.                 END
  24813.  
  24814.                 -- Deactivate virtual (but not virtual anonymous) subscriptions at the distributor
  24815.                 SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSinvalidate_snapshot'
  24816.                 EXEC @retcode = @distproc 
  24817.                     @publisher = @@SERVERNAME, 
  24818.                     @publisher_db = @dbname, 
  24819.                     @publication = @publication
  24820.  
  24821.                 IF @@ERROR <> 0 OR @retcode <> 0
  24822.                     goto UNDO
  24823.  
  24824.                 -- Raise a warning. Snapshot is invalidated. Need to run
  24825.                 -- snapshot agent again..
  24826.                 raiserror(20605, 10, -1)
  24827.             end
  24828.         end
  24829.     end
  24830.     
  24831.     if @need_reinit_subscription = 1
  24832.     begin
  24833.         -- Reinitialize the subscriptions if there are any.
  24834.         -- No need to reinit no_sync subscriptions.
  24835.         -- The query below works for an article or whole publication (@artid == 0)
  24836.         -- Including virtual subscriptions to take care anonymous.
  24837.         if exists (select * from syssubscriptions s where
  24838.             s.status = @active and
  24839.             -- Only include virtual subscription if allow anonymous
  24840.             (s.srvid >= 0 or (@allow_anonymous = 1 and @immediate_sync_ready = 1)) and
  24841.             s.sync_type <> @none and
  24842.             (s.artid = @artid or 
  24843.             (@artid = 0 and exists (select * from 
  24844.                 syspublications p, sysarticles a where
  24845.                 a.artid = s.artid and 
  24846.                 a.pubid = p.pubid and
  24847.                 p.pubid = @pubid))))
  24848.         begin
  24849.             -- Fail and raiserror error
  24850.             if @force_reinit_subscription = 0
  24851.             begin
  24852.                 raiserror(20608, 16, -1)
  24853.                 goto UNDO
  24854.             end
  24855.  
  24856.             if @check_only = 0
  24857.             begin
  24858.                 EXEC @retcode = dbo.sp_reinitsubscription 
  24859.                     @publication = @publication, 
  24860.                     @article = @article,
  24861.                     @subscriber = 'all',
  24862.                     @for_schema_change = 1
  24863.                 IF @@ERROR <> 0 OR @retcode <> 0
  24864.                 BEGIN
  24865.                     GOTO UNDO
  24866.                 END
  24867.                 -- Raise a warning. Subscriptions is reintialized.
  24868.                 raiserror(20606, 10, -1)
  24869.             end
  24870.         end
  24871.     end
  24872.  
  24873.     COMMIT TRAN sp_MSreinit_article
  24874.     
  24875.     return 0
  24876. UNDO:
  24877.     IF @@TRANCOUNT > 0
  24878.     begin
  24879.         ROLLBACK TRAN sp_MSreinit_article
  24880.         COMMIT TRAN 
  24881.     end
  24882.     return 1
  24883. go
  24884.  
  24885. EXEC dbo.sp_MS_marksystemobject sp_MSreinit_article
  24886. GO
  24887.  
  24888.  
  24889. print ''
  24890. print 'Creating procedure sp_MScomputearticlescreationorder'
  24891. go
  24892. CREATE PROCEDURE sp_MScomputearticlescreationorder
  24893.     @publication sysname
  24894. AS
  24895.     SET NOCOUNT ON
  24896.     DECLARE @pubid int 
  24897.     DECLARE @max_level int
  24898.     DECLARE @current_level int
  24899.     DECLARE @update_level int
  24900.     DECLARE @limit int
  24901.     DECLARE @result int
  24902.  
  24903.     SELECT @pubid = NULL
  24904.     -- Get the pubid from syspublications 
  24905.     SELECT @pubid = pubid 
  24906.       FROM syspublications
  24907.      WHERE name = @publication
  24908.  
  24909.     IF @@ERROR <> 0
  24910.         RETURN (1)
  24911.  
  24912.     IF @pubid IS NULL
  24913.     BEGIN
  24914.         RAISERROR(20026, 16, -1, @publication)
  24915.         RETURN (1)
  24916.     END
  24917.  
  24918.     EXEC @result = sp_getapplock @Resource = @publication, 
  24919.                 @LockMode = N'Shared', 
  24920.                 @LockOwner = N'Session', 
  24921.                 @LockTimeout = 0
  24922.  
  24923.     IF @result < 0
  24924.     BEGIN
  24925.         RAISERROR(21385, 16, -1, @publication)
  24926.         RETURN (1)
  24927.     END
  24928.  
  24929.     -- Find out the total number of articles in this publication and
  24930.     -- compute the maximum tree height based on the number of articles in 
  24931.     -- the publication. Here, the tree height is counted from the
  24932.     -- leaf-nodes towards the root(s)
  24933.     SELECT @max_level = COUNT(*) + 10,
  24934.            @limit =2 *  COUNT(*) + 11 
  24935.       FROM sysextendedarticlesview 
  24936.      WHERE pubid = @pubid
  24937.  
  24938.     IF @@ERROR <> 0
  24939.     BEGIN
  24940.         RETURN (1)
  24941.     END
  24942.    
  24943.     -- The following temp table contains the minimal amount of 
  24944.     -- article information that we want to keep around and the current
  24945.     -- computed tree level of the article
  24946.     CREATE TABLE #article_level_info
  24947.     (
  24948.         article         sysname collate database_default not null,
  24949.         source_objid    INT     NOT NULL,
  24950.         tree_level      INT     NOT NULL,
  24951.         ref_level       INT     NOT NULL,
  24952.         major_type      TINYINT NOT NULL  -- 1-view&func, 0-other 
  24953.     )  
  24954.    
  24955.     CREATE CLUSTERED INDEX ucarticle_level_info 
  24956.         ON #article_level_info(source_objid)
  24957.  
  24958.     IF @@ERROR <> 0
  24959.     BEGIN
  24960.         GOTO Failure
  24961.     END
  24962.  
  24963.     -- Populate the article level info table. All articles will be
  24964.     -- assigned 0 as their initial tree level. Having 
  24965.     -- a tree level of 0 means that the algorithm hasn't discovered 
  24966.     -- any objects that the article depends on within the publication.
  24967.  
  24968.     INSERT INTO #article_level_info 
  24969.     SELECT name, objid, 0, 0, 
  24970.         CASE type    
  24971.             WHEN 0x40 THEN 1
  24972.             WHEN 0x80 THEN 1
  24973.             ELSE 0 
  24974.         END
  24975.       FROM sysextendedarticlesview
  24976.      WHERE pubid = @pubid
  24977.       
  24978.     -- To jump-start the algorithm, update the tree_level of 
  24979.     -- all articles with no dependency to @max_level.
  24980.  
  24981.     UPDATE #article_level_info 
  24982.        SET tree_level = @max_level
  24983.      WHERE NOT EXISTS (SELECT * 
  24984.                          FROM sysdepends 
  24985.                         WHERE source_objid = id
  24986.                           and id <> depid)
  24987.     IF @@ERROR <> 0
  24988.         GOTO Failure
  24989.  
  24990.     -- For each increasing tree level starting from @max_level, update the 
  24991.     -- the tree_level of articles depending on objects at the current
  24992.     -- level to current level + 1
  24993.     SELECT @current_level = @max_level
  24994.     WHILE 1 = 1
  24995.     BEGIN
  24996.         SELECT @update_level = @current_level + 1
  24997.  
  24998.         UPDATE #article_level_info
  24999.            SET tree_level = @update_level
  25000.           FROM #article_level_info 
  25001.         INNER JOIN sysdepends d
  25002.             ON #article_level_info.source_objid = d.id 
  25003.         INNER JOIN #article_level_info ali1
  25004.             ON (d.depid = ali1.source_objid       
  25005.                AND ali1.tree_level = @current_level
  25006.                AND d.id <> d.depid)
  25007.     
  25008.         -- Terminate the algorithm if we cannot find any articles 
  25009.         -- depending on articles at the current level     
  25010.         IF @@ROWCOUNT = 0
  25011.             GOTO PHASE1
  25012.  
  25013.         IF @@ERROR <> 0
  25014.             GOTO Failure
  25015.  
  25016.         SELECT @current_level = @current_level + 1
  25017.  
  25018.         -- Although there should not be any circular 
  25019.         -- dependencies among the articles, the following
  25020.         -- check is performed to guarantee that 
  25021.         -- the algorithm will terminate even if there 
  25022.         -- is circular dependency among the articles
  25023.         
  25024.         -- Note that with at least one node per level,
  25025.         -- the current level can never exceed the total 
  25026.         -- number of articles (nodes) unless there is
  25027.         -- circular dependency among the articles.
  25028.         
  25029.         -- @limit is defined to be # of articles + 1
  25030.         -- although @limit = # of articles - 1 will be
  25031.         -- sufficient. This is to make absolutely sure that 
  25032.         -- the algorithm will never terminate too early
  25033.  
  25034.         IF @current_level > @limit
  25035.             GOTO PHASE1
  25036.     END
  25037.  
  25038. PHASE1:
  25039.  
  25040.     -- There may be interdependencies among articles 
  25041.     -- that haven't been included in the previous calculations so
  25042.     -- we compute the proper order among these articles here.
  25043.     SELECT @limit = @max_level - 9
  25044.     SELECT @current_level = 0
  25045.     WHILE 1 = 1
  25046.     BEGIN
  25047.         SELECT @update_level = @current_level + 1
  25048.         
  25049.         UPDATE #article_level_info 
  25050.            SET tree_level = @update_level
  25051.           FROM #article_level_info
  25052.         INNER JOIN sysdepends d
  25053.             ON (#article_level_info.source_objid = d.id
  25054.                 AND #article_level_info.tree_level < @max_level) 
  25055.         INNER JOIN #article_level_info ali1
  25056.             ON (d.depid = ali1.source_objid
  25057.                 AND ali1.tree_level = @current_level
  25058.                 AND d.id <> d.depid)
  25059.         IF @@ROWCOUNT = 0
  25060.             GOTO PHASE2
  25061.         
  25062.         IF @@ERROR <> 0
  25063.             GOTO Failure
  25064.  
  25065.         SELECT @current_level = @current_level + 1
  25066.         IF @current_level > @limit
  25067.             GOTO PHASE2
  25068.     END         
  25069.  
  25070. PHASE2:
  25071.  
  25072.     -- Since transactional doesn't keep the nickname around in 
  25073.     -- sysmergearticles as merge does, we need to compute FK/PK ordering on 
  25074.     -- the fly. 
  25075.     SELECT @current_level = 0
  25076.     SELECT @limit = @max_level - 9
  25077.     WHILE 1 = 1
  25078.     BEGIN
  25079.         SELECT @update_level = @current_level + 1
  25080.         
  25081.         UPDATE #article_level_info
  25082.            SET ref_level = @update_level
  25083.           FROM #article_level_info
  25084.         INNER JOIN sysreferences r
  25085.             ON (#article_level_info.source_objid = r.fkeyid
  25086.                 and r.rkeyid <> r.fkeyid)
  25087.         INNER JOIN #article_level_info ali1
  25088.             ON (r.rkeyid = ali1.source_objid 
  25089.                 AND ali1.ref_level = @current_level)
  25090.         IF @@ROWCOUNT = 0
  25091.             GOTO PHASE3
  25092.  
  25093.         IF @@ERROR <> 0
  25094.             GOTO Failure
  25095.  
  25096.         SELECT @current_level = @current_level + 1
  25097.         IF @current_level > @limit
  25098.             GOTO PHASE3
  25099.     END
  25100.  
  25101. PHASE3:
  25102.  
  25103.     -- Select the articles out of #article_level_info 
  25104.     -- in ascending order of tree_level. This will give
  25105.     -- the proper order in which articles can be created
  25106.     -- without violating the internal dependencies among
  25107.     -- themselves. Note that this algorithm still allows 
  25108.     -- unresolved external references outside the publication.
  25109.     -- All this algorithm can guarantee is that all articles will
  25110.     -- be created successfully using the resulting order if 
  25111.     -- there is no dependent object outside the publication. 
  25112.     -- We need to order the articles in reverse ref_level
  25113.     -- to account for FK/PK constraints when dropping/deleting rows/truncating
  25114.     -- tables on the Subscriber.
  25115.  
  25116.     SELECT article
  25117.       FROM #article_level_info
  25118.     ORDER BY major_type ASC, tree_level ASC, ref_level DESC
  25119.  
  25120.     DROP TABLE #article_level_info
  25121.     RETURN (0)
  25122.  
  25123. Failure:
  25124.  
  25125.     DROP TABLE #article_level_info
  25126.     RETURN (1)
  25127. GO
  25128.  
  25129. exec dbo.sp_MS_marksystemobject sp_MScomputearticlescreationorder
  25130. go
  25131.  
  25132. print ''
  25133. print 'Creating procedure sp_MScomputeunresolvedrefs'
  25134. go
  25135. CREATE PROCEDURE sp_MScomputeunresolvedrefs
  25136.     @publication sysname, -- Must provide the publication name
  25137.     @article     sysname = '%' -- '%' means all articles in the specified publication, otherwise an exact match is performed
  25138. AS
  25139.     SET NOCOUNT ON 
  25140.     DECLARE @pubid int 
  25141.     
  25142.     -- Parameter check: @publication
  25143.  
  25144.     IF @publication IS NULL
  25145.     BEGIN
  25146.         RAISERROR (14043, 16, -1, '@publication')
  25147.         RETURN (1)
  25148.     END
  25149.  
  25150.     SELECT @pubid = NULL 
  25151.     -- Get the pubid of the publication
  25152.     SELECT @pubid = pubid 
  25153.       FROM syspublications
  25154.      WHERE name = @publication
  25155.     
  25156.     IF @pubid IS NULL
  25157.     BEGIN
  25158.         RAISERROR (20026, 11, -1, @publication)
  25159.         RETURN (1)    
  25160.     END
  25161.  
  25162.     SELECT DISTINCT 
  25163.            'article' = a.name, 
  25164.            'dependent object' = o.name, 
  25165.            'dependent object owner' = u.name, 
  25166.            'dependent objectid' = o.id 
  25167.       FROM dbo.sysextendedarticlesview a
  25168.     INNER JOIN sysdepends dep
  25169.         ON a.objid = dep.id
  25170.        AND a.pubid = @pubid
  25171.        AND (@article = '%' OR name = @article)
  25172.        AND dep.depid NOT IN (SELECT objid FROM dbo.sysextendedarticlesview
  25173.                               WHERE pubid = @pubid 
  25174.                                 AND (@article = '%' OR name = @article))
  25175.     INNER JOIN sysobjects o
  25176.         ON dep.depid = o.id
  25177.     INNER JOIN sysusers u
  25178.         ON u.uid = o.uid          
  25179. GO
  25180.  
  25181.  
  25182. exec dbo.sp_MS_marksystemobject sp_MScomputeunresolvedrefs
  25183. go
  25184.  
  25185. /*
  25186.  * Name :       sp_MShelptranconflictpublications
  25187.  * Called by:    sp_MShelpconflictpublications
  25188.  * Description: This sp returns a list of queued publications or subscriptions in the current
  25189.  *    database that may have conflicts. Results are ordered by publication
  25190.  *    name. * Parameters:  1. publication_type( sysname; '%'==ALL  | 'queued' )
  25191.  * Output Result Set has the following structure:
  25192.  *  
  25193. ----------------------------------------------------------------------------------
  25194.  *      Name                Datatype                Description
  25195.  *  
  25196. ----------------------------------------------------------------------------------
  25197.  *  a. name     (sysname)      Publication name
  25198.  *  b. publication_type  (varchar(9))  'merge' | 'queued' | 'immediate' (reserved)
  25199.  *  c. merge_pub_id   (uniqueidentifier) Merge publication identifier
  25200.  *  d. tran_pub_id  (integer)   Queued publication identifier 
  25201.  *  e. sub_agent_id    (integer)    Unique publication identifier on a tran subscriber
  25202.  *  NOTE: In case of queued tran publications, either d or e will have a value at any time
  25203.  *  and this will also indicate, if we are processing a subscriber of a publication (d 
  25204.  *  will be NULL and e will have a value) or if we are processing the publisher side (d
  25205.  *  will have a value and e will be NULL)
  25206.  */ 
  25207.  
  25208. raiserror('Creating procedure sp_MShelptranconflictpublications', 0,1)
  25209. GO
  25210.  
  25211. create procedure sp_MShelptranconflictpublications (
  25212.      @publication_type    sysname = 'queued' )        -- '%'==ALL | 'queued'
  25213. as
  25214. begin
  25215.     set nocount on
  25216.     declare @merge_pub_id uniqueidentifier
  25217.     
  25218.     --
  25219.     -- validate
  25220.     --
  25221.     if (@publication_type NOT IN ('%', 'queued'))
  25222.     begin
  25223.         raiserror('sp_MShelptranconflictpublications(debug): Invalid @publication_type=%s specified', 16, 1, @publication_type)
  25224.         return (1)
  25225.     end
  25226.         
  25227.     --
  25228.     -- create a temp table for results
  25229.     --
  25230.      create table #cftpublications ( publication sysname collate database_default, t_pub_id integer, s_agent_id integer)
  25231.  
  25232.      --
  25233.      -- process publisher info
  25234.      --
  25235.      if exists (select * from sysobjects where name = 'syspublications')
  25236.      begin
  25237.          insert into #cftpublications(publication, t_pub_id)
  25238.              select name, pubid from syspublications
  25239.          if (@@error != 0)
  25240.          begin
  25241.             raiserror('sp_MShelptranconflictpublications(debug): insert for tran publications failed', 16, 1)
  25242.             return (1)
  25243.          end
  25244.      end
  25245.  
  25246.      --
  25247.      -- process subscriber info
  25248.      --
  25249.      if exists (select * from sysobjects where name = 'MSsubscription_agents')
  25250.      begin
  25251.          insert into #cftpublications(publication, s_agent_id)
  25252.              select publication, id from MSsubscription_agents where update_mode in (2,3,4,5)
  25253.      end
  25254.  
  25255.      --
  25256.      -- now do a select on the temp table
  25257.      --
  25258.      select    'name'                = publication,
  25259.              'publication_type'    = N'queued',
  25260.              'merge_pub_id'         = @merge_pub_id,
  25261.              'tran_pub_id'         = t_pub_id,
  25262.              'sub_agent_id'        = s_agent_id
  25263.      from     #cftpublications
  25264.              
  25265.      --
  25266.      -- all done
  25267.      --
  25268.      return 0
  25269. end
  25270. go
  25271.  
  25272. exec dbo.sp_MS_marksystemobject sp_MShelptranconflictpublications
  25273. go
  25274.  
  25275. /*
  25276.  * Name :       sp_MShelptranconflictcounts
  25277.  * Description: This sp returns the count of conflicts (from each conflict table) in 
  25278.  *    each publication. Results can optionally be filtered to include only a 
  25279.  *    single publication. Results are always ordered by article name. Only 
  25280.  *    articles with non-zero conflict counts are returned.
  25281.  * Parameters:  1. Publication Name( sysname; default '%'==ALL PUBLICATIONS)
  25282.  * Output Result Set has the following structure:
  25283.  *  
  25284. ----------------------------------------------------------------------------------
  25285.  *      Name                Datatype                Description
  25286.  *  
  25287. ----------------------------------------------------------------------------------
  25288.  *  a. article    (nvarchar(256))      owner qualified Article name
  25289.  *  b. conflict_table  (sysname)   Associated conflict table (owner qualified)
  25290.  *  c. queued_source_proc (sysname)   Queued proc to get source row - sp_MSgettrancftsrcrow
  25291.  *  d. centralized_conflicts(bit)    Centralized (1) or Decentralized (0) 
  25292.  *            conflicts specified by the article
  25293.  *  e. conflict_count  (integer)           Count of (insert, update and delete) conflicts in 
  25294.  *            the conflict table for this article
  25295.  */
  25296. raiserror('Creating procedure sp_MShelptranconflictcounts', 0,1)
  25297. GO
  25298.  
  25299. create procedure sp_MShelptranconflictcounts ( 
  25300.     @publication_name sysname = '%' )
  25301. as 
  25302. begin
  25303.     set nocount on 
  25304.  
  25305.     declare @pubid int
  25306.             ,@centralized_conflicts bit
  25307.             ,@article sysname
  25308.             ,@artid int
  25309.             ,@conflict_table sysname
  25310.             ,@cft_tabid int
  25311.             ,@spname sysname
  25312.             ,@cmd nvarchar(4000)
  25313.             ,@conflicts_count int
  25314.             ,@publisher sysname
  25315.             ,@publisher_db sysname
  25316.             ,@owner sysname
  25317.  
  25318.     select @spname = 'sp_MSgettrancftsrcrow'
  25319.  
  25320.     --
  25321.     -- create temp table for results
  25322.     --
  25323.     create table #result_list ( article nvarchar(256) collate database_default, conflict_table sysname collate database_default null,  
  25324.         centralized_conflicts bit, conflict_count integer)
  25325.  
  25326.     create table #conflict_list ( artid sysname collate database_default, conflict_count int, sub_agent_id int )
  25327.  
  25328.     -- 
  25329.     -- process publisher
  25330.     --
  25331.     if exists ( select * from sysobjects where name = 'sysarticles')
  25332.     begin
  25333.         --
  25334.         -- Walk through each publication that allows queued operation
  25335.         --
  25336.         if ( @publication_name = '%' )
  25337.             declare hCPubCursor CURSOR LOCAL FAST_FORWARD fast_forward for
  25338.                 select pubid, centralized_conflicts
  25339.                 from syspublications
  25340.                 where allow_queued_tran = 1
  25341.         else
  25342.             declare hCPubCursor CURSOR LOCAL FAST_FORWARD fast_forward for
  25343.                 select pubid, centralized_conflicts
  25344.                 from syspublications
  25345.                 where allow_queued_tran = 1
  25346.                     and name = @publication_name
  25347.  
  25348.         open hCPubCursor
  25349.         fetch hCPubCursor into @pubid, @centralized_conflicts
  25350.         while ( @@fetch_status != -1 )
  25351.         begin
  25352.             --
  25353.             -- Walk through each article in this publication
  25354.             --
  25355.             declare hCArtCursor CURSOR LOCAL FAST_FORWARD fast_forward for
  25356.                 select a.name, b.conflict_tableid, a.artid
  25357.                 from sysarticles a join
  25358.                     sysarticleupdates b on
  25359.                         a.artid = b.artid and
  25360.                         a.pubid = b.pubid
  25361.                 where a.pubid = @pubid
  25362.  
  25363.             open hCArtCursor
  25364.             fetch hCArtCursor into @article, @cft_tabid, @artid
  25365.             while ( @@fetch_status != -1 )
  25366.             begin
  25367.                 --
  25368.                 -- get the owner qualified conflict table name
  25369.                 --
  25370.                 select @owner = QUOTENAME(user_name(OBJECTPROPERTY(@cft_tabid, 'OwnerId')))
  25371.                 select @conflict_table = @owner + N'.' + QUOTENAME(OBJECT_NAME(@cft_tabid))
  25372.  
  25373.                 --
  25374.                 -- Get all the conflict counts
  25375.                 --
  25376.                 select @cmd = 'select ' + cast(@artid as nvarchar(10)) +  
  25377.                     ', count(*) from ' + @conflict_table + 
  25378.                     ' where conflict_type in (1, 5, 7) and pubid = ' + 
  25379.                     cast(@pubid as nvarchar(10))
  25380.                 insert into #conflict_list ( artid, conflict_count )
  25381.                     exec ( @cmd )
  25382.  
  25383.                 select @conflicts_count = NULLIF(conflict_count, 0)
  25384.                 from #conflict_list
  25385.                 where artid = @artid
  25386.                 
  25387.                 if (@conflicts_count > 0)
  25388.                 begin
  25389.                     --
  25390.                     -- add a row to the #result_list
  25391.                     --
  25392.                     insert into #result_list ( article, conflict_table, centralized_conflicts, conflict_count )
  25393.                         select @owner + N'.' + QUOTENAME(@article), @conflict_table, @centralized_conflicts, @conflicts_count
  25394.                 end
  25395.                 
  25396.                 --
  25397.                 -- fetch next row from hCArtCursor
  25398.                 --
  25399.                 fetch hCArtCursor into @article, @cft_tabid, @artid
  25400.             end
  25401.             close hCArtCursor
  25402.             deallocate hCArtCursor
  25403.  
  25404.             --
  25405.             -- fetch next row from hCPubCursor
  25406.             --
  25407.             fetch hCPubCursor into @pubid, @centralized_conflicts    
  25408.         end
  25409.         close hCPubCursor
  25410.         deallocate hCPubCursor
  25411.     end
  25412.  
  25413.     --
  25414.     -- process subscriber side
  25415.     --
  25416.     delete #conflict_list
  25417.     if exists ( select * from sysobjects where name = 'MSsubscription_articles')
  25418.     begin
  25419.         --
  25420.         -- Walk through each subscription that allows queued operation
  25421.         --
  25422.         if ( @publication_name = '%' )
  25423.             declare hCPubCursor CURSOR LOCAL FAST_FORWARD fast_forward for
  25424.                 select id, 0, publisher, publisher_db 
  25425.                 from MSsubscription_agents 
  25426.                 where update_mode in (2,3,4,5)
  25427.         else
  25428.             declare hCPubCursor CURSOR LOCAL FAST_FORWARD fast_forward for
  25429.                 select id, 0, publisher, publisher_db 
  25430.                 from MSsubscription_agents 
  25431.                 where update_mode in (2,3,4,5)
  25432.                     and publication = @publication_name
  25433.  
  25434.         open hCPubCursor
  25435.         fetch hCPubCursor into @pubid, @centralized_conflicts, @publisher, @publisher_db
  25436.         while ( @@fetch_status != -1 )
  25437.         begin
  25438.             --
  25439.             -- Walk through each article in this subscribed publication
  25440.             --
  25441.             declare hCArtCursor CURSOR LOCAL FAST_FORWARD fast_forward for
  25442.                 select a.article, OBJECT_ID(a.cft_table), a.artid
  25443.                 from MSsubscription_articles a join
  25444.                     MSsubscription_agents b on
  25445.                         a.agent_id = b.id
  25446.                 where b.id = @pubid
  25447.  
  25448.             open hCArtCursor
  25449.             fetch hCArtCursor into @article, @cft_tabid, @artid
  25450.             while ( @@fetch_status != -1 )
  25451.             begin
  25452.                 --
  25453.                 -- get the owner qualified conflict table name
  25454.                 --
  25455.                 select @owner = QUOTENAME(user_name(OBJECTPROPERTY(@cft_tabid, 'OwnerId')))
  25456.                 select @conflict_table = @owner + N'.' + QUOTENAME(OBJECT_NAME(@cft_tabid))
  25457.  
  25458.                 --
  25459.                 -- Get all the conflict counts
  25460.                 --
  25461.                 select @cmd = 'select ' + cast(@artid as nvarchar(10)) +  
  25462.                     ', count(*), ' + cast(@pubid as nvarchar(10)) + 
  25463.                     ' from ' + @conflict_table + 
  25464.                     ' where conflict_type in (1, 5, 7) 
  25465.                         and origin_datasource = ''' + @publisher + '.' + @publisher_db + ''''
  25466.                     
  25467.                 insert into #conflict_list ( artid, conflict_count, sub_agent_id )
  25468.                     exec ( @cmd )
  25469.  
  25470.                 select @conflicts_count = NULLIF(conflict_count, 0)
  25471.                 from #conflict_list
  25472.                 where artid = @artid and sub_agent_id = @pubid
  25473.                 
  25474.                 if (@conflicts_count > 0)
  25475.                 begin
  25476.                     --
  25477.                     -- add a row to the #result_list
  25478.                     --
  25479.                     insert into #result_list ( article, conflict_table, centralized_conflicts, conflict_count )
  25480.                         select @owner + N'.' + QUOTENAME(@article), @conflict_table, @centralized_conflicts, @conflicts_count
  25481.                 end
  25482.                 
  25483.                 --
  25484.                 -- fetch next row from hCArtCursor
  25485.                 --
  25486.                 fetch hCArtCursor into @article, @cft_tabid, @artid
  25487.             end
  25488.             close hCArtCursor
  25489.             deallocate hCArtCursor
  25490.  
  25491.             --
  25492.             -- fetch next row from hCPubCursor
  25493.             --
  25494.             fetch hCPubCursor into @pubid, @centralized_conflicts, @publisher, @publisher_db    
  25495.         end
  25496.         close hCPubCursor
  25497.         deallocate hCPubCursor
  25498.     end
  25499.  
  25500.     --
  25501.     -- do a select for results
  25502.     --
  25503.     select     article,
  25504.             conflict_table,
  25505.             'queued_source_proc' = @spname,
  25506.             centralized_conflicts,
  25507.             conflict_count
  25508.     from #result_list
  25509.  
  25510.     --
  25511.     -- all done
  25512.     --
  25513.     return (0)
  25514. end
  25515. go
  25516.  
  25517. exec dbo.sp_MS_marksystemobject sp_MShelptranconflictcounts
  25518. go 
  25519.  
  25520. /*
  25521.  * Name :       sp_MSgettranconflictrow
  25522.  * Description: This sp returns a result set containing the requested conflict row(s) 
  25523.  *    for a queued publication. Result set ordered by transaction id and 
  25524.  *    row identifier.
  25525.  * Parameters:  
  25526.  *      1. tran_id    nvarchar(70). ('%'==ALL transactions for the article)
  25527.  *    2. row_id ( uniqueidentifer or '%'==ALL rows for a given transaction)
  25528.  *    3. conflict_table    (sysname)
  25529.  * Output Result Set has the following structure:
  25530.  *  
  25531. ----------------------------------------------------------------------------------
  25532.  *      Name                Datatype                Description
  25533.  *  
  25534. ----------------------------------------------------------------------------------
  25535.  * returns the current row (all columns) from conflict table with specified tran_id, (row_id)insert_date
  25536.  */
  25537. raiserror('Creating procedure sp_MSgettranconflictrow', 0,1)
  25538. GO
  25539.  
  25540. create procedure sp_MSgettranconflictrow ( 
  25541.     @tran_id sysname = '%',                        -- % = ALL
  25542.     @row_id sysname = '%',                        -- % = ALL
  25543.     @conflict_table sysname)
  25544. as 
  25545. begin
  25546.     set nocount on
  25547.     declare @cmd nvarchar(4000)
  25548.             ,@whcmd nvarchar(4000)
  25549.  
  25550.     select @cmd = N'select * from ' + @conflict_table 
  25551.     if (@tran_id != N'%')
  25552.     begin
  25553.         if (@whcmd is null)
  25554.             select @whcmd = N'tranid = ''' + @tran_id + N''''
  25555.         else
  25556.             select @whcmd = @whcmd + N' and tranid = ''' + @tran_id + N''''        
  25557.     end
  25558.     if (@row_id != N'%')
  25559.     begin
  25560.         if (@whcmd is null)
  25561.             select @whcmd = N'qcfttabrowid = ''' + @row_id + N''''
  25562.         else
  25563.             select @whcmd = @whcmd + N' and qcfttabrowid = ''' + @row_id + N''''
  25564.     end
  25565.  
  25566.     if (@whcmd is not null)
  25567.     begin
  25568.         select @cmd = @cmd + N' where ' + @whcmd
  25569.     end
  25570.     
  25571.     execute (@cmd)
  25572. end
  25573. go
  25574.  
  25575. exec dbo.sp_MS_marksystemobject sp_MSgettranconflictrow
  25576. go
  25577.  
  25578. /*
  25579.  * Name :       sp_MSgettrancftsrcrow
  25580.  * Description: This sp returns a result set containing the requested source row 
  25581.  *     pertaining to a respective conflict row in conflict table (same PK/unique key)
  25582.  *     for a queued publication. Result set ordered by transaction id and row identifier
  25583.  *       for the conflict table.
  25584.  * Parameters:  1. tran_id (nvarchar(70))
  25585.  *      2. row_id uniqueidentifer - cannot be null
  25586.  *    3. conflict_table (nvarchar(256) - owner qualified table name - [owner].[tabname]
  25587.  *      4. is_subscriber bit=0                        -- Publisher = 0, Subscriber = 1
  25588.  * Output Result Set has the following structure:
  25589.  *  
  25590. ----------------------------------------------------------------------------------
  25591.  *      Name                Datatype                Description
  25592.  *  
  25593. ----------------------------------------------------------------------------------
  25594.  * returns the current row (all columns) from from source table with same PK for the row in 
  25595.  * conflict table with specified tran_id, insert_date
  25596.  */
  25597. raiserror('Creating procedure sp_MSgettrancftsrcrow', 0,1)
  25598. GO
  25599.  
  25600. create procedure sp_MSgettrancftsrcrow ( 
  25601.     @tran_id sysname,
  25602.     @row_id sysname,
  25603.     @conflict_table nvarchar(256),
  25604.     @is_subscriber bit,
  25605.     @is_debug bit=0 )
  25606. as 
  25607. begin
  25608.     set nocount on
  25609.     declare @decllist nvarchar(4000)
  25610.             ,@sellist nvarchar(4000)
  25611.             ,@wherelist nvarchar(4000)
  25612.             ,@cmd nvarchar(4000)
  25613.             ,@cmdrow nvarchar(4000)
  25614.             ,@srctable sysname
  25615.             ,@srctabid int
  25616.             ,@srcowner sysname
  25617.             ,@columns  binary(32)
  25618.             ,@indid int
  25619.             ,@indkey int
  25620.             ,@key sysname
  25621.             ,@this_col int
  25622.             ,@col sysname
  25623.             ,@typestring nvarchar(60)
  25624.             ,@dbname sysname
  25625.             ,@retcode smallint
  25626.             ,@unqualified_cft_tab sysname
  25627.             ,@startoffset int
  25628.             
  25629.     --
  25630.     -- validate
  25631.     --
  25632.     if ((@tran_id is null) or (@row_id is null) or 
  25633.         (@conflict_table is null) or (@is_subscriber is null))
  25634.     begin
  25635.         raiserror('sp_MSgettrancftsrcrow(debug): @tran_id,@row_id,@conflict_table,@is_subscriber cannot be null', 16, 1)
  25636.         return (1)
  25637.     end
  25638.  
  25639.     --
  25640.     -- check if the conflict table is owner qualified
  25641.     --
  25642.     select @startoffset = charindex(N'].[', @conflict_table, 0)
  25643.     select @unqualified_cft_tab = case when (@startoffset > 0) 
  25644.         then substring(@conflict_table, @startoffset + 2, len(@conflict_table) - @startoffset - 1)
  25645.         else quotename(@conflict_table) end
  25646.         
  25647.     --
  25648.     -- get the source table info
  25649.     --
  25650.     if (@is_subscriber = 1)
  25651.     begin
  25652.         select @srcowner = owner, @srctable = dest_table, 
  25653.             @srctabid = OBJECT_ID(dest_table), @columns = columns
  25654.         from MSsubscription_articles
  25655.         where quotename(cft_table) = @unqualified_cft_tab
  25656.     end
  25657.     else
  25658.     begin
  25659.         select @srcowner = user_name(OBJECTPROPERTY(objid,'OwnerId')), @srctable = OBJECT_NAME(objid), 
  25660.             @srctabid = objid, @columns = columns
  25661.         from sysarticles a join sysarticleupdates b on
  25662.             a.pubid = b.pubid and 
  25663.             a.artid = b.artid
  25664.         where b.conflict_tableid = OBJECT_ID(@conflict_table)
  25665.     end
  25666.  
  25667.     --
  25668.     -- create code for the following :
  25669.     -- select the row of conflict with given tranid and insertdate
  25670.     -- retrieve the values of the PK/UI columns for the source table from this row in cft_table
  25671.     -- select all columns from source table using the values in a where clause for PK/UI
  25672.     --
  25673.  
  25674.     --
  25675.     -- PK/UI check for source table
  25676.     --
  25677.     exec @indid = dbo.sp_MStable_has_unique_index @srctabid
  25678.     if (@indid = 0)
  25679.     begin
  25680.         raiserror('sp_MSgettrancftsrcrow(debug):source table %s does not have unique index', 16, 1, @srctable)
  25681.         return (1)
  25682.     end
  25683.  
  25684.     --
  25685.     -- create temp tables
  25686.     --
  25687.     create table #decltext ( c1 int identity NOT NULL, cmdtext nvarchar(4000) collate database_default null)
  25688.     create table #seltext ( c1 int identity NOT NULL, cmdtext nvarchar(4000) collate database_default null)
  25689.     create table #wheretext ( c1 int identity NOT NULL, cmdtext nvarchar(4000) collate database_default null)
  25690.  
  25691.     --
  25692.     -- walk through each column in PK/UI and build parts of code
  25693.     --
  25694.     select @indkey = 1
  25695.     while (@indkey <= 16)
  25696.     begin    
  25697.         select @key = index_col(@srctable, @indid, @indkey)
  25698.         if (@key is null)
  25699.         begin
  25700.             select @indkey = 16
  25701.         end
  25702.         else
  25703.         begin
  25704.             --
  25705.             -- get the column index in the source table for this index key
  25706.             --
  25707.             exec dbo.sp_MSget_col_position @srctabid, @columns, @key, @col output, @this_col output
  25708.  
  25709.             --
  25710.             -- get the typestring for this column in source table
  25711.             --
  25712.             exec dbo.sp_gettypestring @srctabid, @this_col, @typestring OUTPUT
  25713.  
  25714.             --
  25715.             -- build command strings
  25716.             --
  25717.             if (@decllist is NULL)
  25718.                 select @decllist = N'declare @' + @col + N' ' + @typestring
  25719.             else
  25720.                 select @decllist = N' ,@' + @col + N' ' + @typestring
  25721.             
  25722.             if (@sellist is NULL)
  25723.                 select @sellist = N'select @' + @col + N' = ' + quotename(@key)
  25724.             else
  25725.                 select @sellist = N' ,@' + @col + N' = ' + quotename(@key)
  25726.                 
  25727.             if (@wherelist is NULL)
  25728.                 select @wherelist = N'where ' + quotename(@key) + N' = @' + @col
  25729.             else
  25730.                 select @wherelist = N' ,' + quotename(@key) + N' = @' + @col
  25731.  
  25732.             --
  25733.             -- store them in the temp tables
  25734.             --
  25735.             insert into #decltext(cmdtext) values(@decllist)
  25736.             insert into #seltext(cmdtext) values(@sellist)
  25737.             insert into #wheretext(cmdtext) values(@wherelist)
  25738.             
  25739.         end
  25740.         select @indkey = @indkey + 1
  25741.     end
  25742.  
  25743.     --
  25744.     -- Now put all the code in order in the codetext
  25745.     --
  25746.     if exists (select * from sysobjects where name = 'MSsrcrow_codetext')
  25747.         drop table MSsrcrow_codetext
  25748.         
  25749.     create table MSsrcrow_codetext ( step int identity NOT NULL, cmdtext nvarchar(4000) NULL)
  25750.  
  25751.     insert into MSsrcrow_codetext(cmdtext)
  25752.         select cmdtext from #decltext order by c1
  25753.     insert into MSsrcrow_codetext(cmdtext) values (N' ')
  25754.     insert into MSsrcrow_codetext(cmdtext)
  25755.         select cmdtext from #seltext order by c1
  25756.     select @cmd = N' 
  25757.     from ' 
  25758.  
  25759.     if (@startoffset > 0)
  25760.         select @cmd = @cmd + @conflict_table
  25761.     else
  25762.         select @cmd = @cmd + quotename(@srcowner) + N'.' + @unqualified_cft_tab
  25763.         
  25764.     select @cmd = @cmd + N'
  25765.     where tranid = ''' + @tran_id + ''' and qcfttabrowid = ''' + @row_id + ''' '
  25766.     insert into MSsrcrow_codetext(cmdtext) values (@cmd)
  25767.     select @cmd = N'select * from ' + quotename(@srcowner) + N'.' + quotename(@srctable) + N' '
  25768.     insert into MSsrcrow_codetext(cmdtext) values (@cmd)
  25769.     insert into MSsrcrow_codetext(cmdtext)
  25770.         select cmdtext from #wheretext order by c1
  25771.  
  25772.     --
  25773.     -- now execute the code we just built
  25774.     --
  25775.     if (@is_debug = 0)
  25776.     begin
  25777.         --
  25778.         -- Build 139:
  25779.         -- NOTE xp_execresultset should work here but does not
  25780.         -- return for a long time. Using exec() - should revisit
  25781.         -- this for more stable builds
  25782.         --
  25783.         declare #srccursor cursor local FAST_FORWARD FOR 
  25784.         select cmdtext from MSsrcrow_codetext order by step 
  25785.         FOR READ ONLY
  25786.  
  25787.         select @cmd = N' '
  25788.         select @dbname = db_name()
  25789.         open #srccursor
  25790.         fetch #srccursor into @cmdrow
  25791.         while (@@FETCH_STATUS = 0)
  25792.         begin
  25793.             select @cmd = @cmd + @cmdrow
  25794.             fetch #srccursor into @cmdrow    
  25795.         end        
  25796.         close #srccursor
  25797.         deallocate #srccursor
  25798.         
  25799.         execute(@cmd)
  25800.         if (@@error != 0)
  25801.         begin
  25802.             raiserror('sp_MSgettrancftsrcrow(debug): execute() failed for [%s] in db [%s] ', 16, 1, @cmd, @dbname)
  25803.             return (1)
  25804.         end
  25805.  
  25806.     end
  25807.     else
  25808.         select cmdtext from MSsrcrow_codetext order by step 
  25809.  
  25810.     --
  25811.     -- all done
  25812.     --
  25813.     drop table MSsrcrow_codetext
  25814.     return 0
  25815. end
  25816. go
  25817.  
  25818. exec dbo.sp_MS_marksystemobject sp_MSgettrancftsrcrow
  25819. go
  25820.  
  25821. /*
  25822.  * Name :       sp_MSdeletetranconflictrow
  25823.  * Description: This sp deletes the requested conflict row(s) for a queued publication. 
  25824.  *    Can delete all conflicts in a transaction by specifying only tran_id.
  25825.  * Parameters:  1. tran_id    (nvarchar(70))
  25826.  *    2. row_id ( uniqueidentifier or '%'==ALL conflicts for a given transaction)
  25827.  * Output  None.
  25828.  *  
  25829. ----------------------------------------------------------------------------------
  25830.  *      Name                Datatype                Description
  25831.  *  
  25832. ----------------------------------------------------------------------------------
  25833.  */ 
  25834. raiserror('Creating procedure sp_MSdeletetranconflictrow', 0,1)
  25835. GO
  25836.  
  25837. create procedure sp_MSdeletetranconflictrow ( 
  25838.     @tran_id sysname,
  25839.     @row_id sysname = '%',                        -- % = ALL
  25840.     @conflict_table sysname)
  25841. as 
  25842. begin
  25843.     set nocount on
  25844.     declare @cmd nvarchar(4000)
  25845.  
  25846.     if (@conflict_table is NULL)
  25847.     begin
  25848.         raiserror('sp_MSdeletetranconflictrow(debug) - @conflict_table cannot be null', 16, 1)
  25849.         return (1)
  25850.     end
  25851.  
  25852.     select @cmd = 'delete ' + @conflict_table +
  25853.         ' where tranid = ''' + @tran_id + ''''
  25854.  
  25855.     if (@row_id != N'%')
  25856.     begin
  25857.         select @cmd = @cmd +
  25858.         ' and qcfttabrowid = ''' + @row_id + ''''
  25859.     end
  25860.     
  25861.     execute (@cmd)
  25862. end
  25863. go
  25864.  
  25865. exec dbo.sp_MS_marksystemobject sp_MSdeletetranconflictrow
  25866. go
  25867.  
  25868.  
  25869. raiserror('Creating procedure sp_MSexternalfkreferences', 0,1)
  25870. go
  25871.  
  25872. create procedure sp_MSexternalfkreferences
  25873.     @publication sysname,
  25874.     @article     sysname
  25875. as
  25876.     declare @pubid int
  25877.     declare @objid int
  25878.     declare @retcode int
  25879.  
  25880.     exec @retcode = dbo.sp_MSreplcheck_publish
  25881.     if @@ERROR <> 0 or @retcode <> 0
  25882.         return (1)
  25883.  
  25884.     select @pubid = pubid from dbo.syspublications where name = @publication
  25885.     select @objid = objid from dbo.sysarticles where pubid = @pubid and name = @article
  25886.  
  25887.     select rkeyid, fkeyid from dbo.sysreferences
  25888.         where fkeyid = @objid
  25889.           and rkeyid not in (select objid from dbo.sysarticles where pubid = @pubid)      
  25890. go
  25891. exec dbo.sp_MS_marksystemobject sp_MSexternalfkreferences
  25892. go
  25893.  
  25894. --
  25895. -- This proc is called by sync/queued tran generated article procs
  25896. -- to get the reinitialization status of a subscription for a given article
  25897. --
  25898. raiserror('Creating procedure sp_MSgetarticlereinitvalue', 0,1)
  25899. go
  25900. create procedure sp_MSgetarticlereinitvalue (
  25901.     @subscriber         sysname = NULL,
  25902.     @subscriberdb         sysname = NULL,
  25903.     @artid                 int = NULL, 
  25904.     @reinit                 int output
  25905. )
  25906. as
  25907. begin
  25908.     set NOCOUNT ON
  25909.     declare @orig_srvid int
  25910.     
  25911.     --
  25912.     -- return NULL if no parameters supplied
  25913.     --
  25914.     if ((@subscriber IS NULL) or (@subscriberdb IS NULL) or (@artid IS NULL))
  25915.     begin
  25916.         select @reinit = NULL
  25917.         return 1
  25918.     end
  25919.  
  25920.     select @orig_srvid = srvid from master.dbo.sysservers where UPPER(srvname) = UPPER(@subscriber) collate database_default
  25921.     select @reinit = queued_reinit 
  25922.     from syssubscriptions 
  25923.     where 
  25924.         artid = @artid 
  25925.         and srvid = @orig_srvid
  25926.         and dest_db = @subscriberdb
  25927.  
  25928.     -- All done
  25929.     return 0
  25930. end
  25931. go
  25932.  
  25933. exec dbo.sp_MS_marksystemobject sp_MSgetarticlereinitvalue
  25934. go
  25935.  
  25936. --
  25937. -- this proc is be used by queued tran UPDATE conflict resolution SPs. It
  25938. -- takes as input a given article and the update bitmask and decides if 
  25939. -- PRIMARY KEY update is taking place returns the following return codes
  25940. --    -1 : Error in execution
  25941. --      0 : Not a PK update
  25942. --     1 : PK update
  25943. --
  25944. raiserror('Creating procedure sp_MSispkupdateinconflict', 0,1)
  25945. go
  25946. create proc sp_MSispkupdateinconflict (
  25947.     @pubid int
  25948.     ,@artid int
  25949.     ,@bitmap varbinary(4000)
  25950. )
  25951. as
  25952. begin
  25953.     declare @retcode int
  25954.         ,@columns binary(32)
  25955.         ,@tabname sysname
  25956.         ,@tabid int
  25957.         ,@indid int
  25958.         ,@indkey int
  25959.         ,@key sysname
  25960.         ,@colid int
  25961.         ,@isset int
  25962.         ,@artcol int
  25963.         ,@bytepos int
  25964.         ,@bitpos int
  25965.  
  25966.     --
  25967.     -- initalize and validate
  25968.     --
  25969.     select @columns = [columns]
  25970.         ,@tabid = objid
  25971.         ,@indkey = 1
  25972.         ,@artcol = 0
  25973.     from dbo.sysarticles
  25974.     where (artid = @artid) and (pubid = @pubid)
  25975.  
  25976.     if (@tabid is null)
  25977.     begin
  25978.         raiserror('sp_MSispkupdateinconflict(Debug): invalid pub and article id : %s.%s', 
  25979.                 16, -1, @pubid, @artid)
  25980.         return -1
  25981.     end
  25982.     
  25983.     select @tabname = QUOTENAME(user_name(OBJECTPROPERTY(@tabid, 'OwnerId'))) collate database_default 
  25984.             + N'.' + QUOTENAME(object_name( @tabid )) collate database_default
  25985.  
  25986.     --
  25987.     -- get the Primary Key Index
  25988.     --
  25989.     select @indid = i.indid 
  25990.     from dbo.sysindexes i 
  25991.     where ((i.status & 2048) != 0) and (i.id = @tabid)
  25992.     if (@indid is null)
  25993.     begin
  25994.         raiserror('sp_MSispkupdateinconflict(Debug): Cannot find primary key for %s', 
  25995.                 16, -1, @tabname)
  25996.         return -1
  25997.     end
  25998.     
  25999.     --
  26000.     -- create an enumeration of all the columns that are part of PK
  26001.     --
  26002.     create table #pkcoltab(pkindex int identity, keyname sysname collate database_default not null)
  26003.     while (@indkey <= 16)
  26004.     begin
  26005.         select @key = index_col( @tabname, @indid, @indkey )
  26006.         if (@key is null)
  26007.             break
  26008.         else
  26009.             insert into #pkcoltab(keyname) values(@key)
  26010.  
  26011.         select @indkey = @indkey + 1
  26012.     end
  26013.  
  26014.     --
  26015.     -- now walk through each article col and if it is
  26016.     -- a part of PK, then check if the update bitmap bit 
  26017.     -- corresponding to any article column is set
  26018.     --
  26019.     DECLARE #hCColid CURSOR LOCAL FAST_FORWARD FOR 
  26020.         select colid, [name] from dbo.syscolumns 
  26021.         where id = @tabid order by colid asc
  26022.  
  26023.     OPEN #hCColid
  26024.     FETCH #hCColid INTO @colid, @key
  26025.     WHILE (@@fetch_status != -1)
  26026.     begin
  26027.         exec @isset = dbo.sp_isarticlecolbitset @colid, @columns
  26028.         if (@isset != 0)
  26029.         begin
  26030.             --
  26031.             -- this column is part of the article
  26032.             --
  26033.             select @artcol = @artcol + 1
  26034.             if exists (select * from #pkcoltab where keyname = @key)
  26035.             begin
  26036.                 --
  26037.                 -- this column is part of PK
  26038.                 --
  26039.                 select     @bytepos = 1 + (@artcol-1) / 8 
  26040.                     ,@bitpos = power(2, (@artcol-1) % 8 )
  26041.  
  26042.                 --
  26043.                 -- if the update bitmap has bit set then
  26044.                 -- then it is a PK update
  26045.                 --
  26046.                 if ((substring(@bitmap, @bytepos, 1) & @bitpos) = @bitpos)
  26047.                     return 1
  26048.             end
  26049.         end        
  26050.  
  26051.         --
  26052.         -- get the next column
  26053.         --
  26054.         FETCH #hCColid INTO @colid, @key
  26055.     end
  26056.     CLOSE #hCColid
  26057.     DEALLOCATE #hCColid
  26058.     drop table #pkcoltab
  26059.  
  26060.     --
  26061.     -- if we have reached here then it mean the update does not
  26062.     -- affect PK columns, cleanup and return
  26063.     --
  26064.     return 0
  26065. end
  26066. go
  26067.  
  26068. EXEC dbo.sp_MS_marksystemobject sp_MSispkupdateinconflict
  26069. GO
  26070.  
  26071. --
  26072. -- sp_ivindexhasnullcols
  26073. --
  26074. -- Proc to validate a indexed view - prior to enabling a indexed view
  26075. -- ,this proc is used to make sure the I.V. clustered index is unique
  26076. -- and does contain any column that can be NULL
  26077. -- 
  26078. -- Parameters:
  26079. --
  26080. --    @viewname sysname         name of the view
  26081. --    ,@fhasnullcols bit         value of 1 if view index has columns that allow NULL
  26082. --                            value of 0 otherwise (returns 0 if error in execution)
  26083. --
  26084. -- Returns:
  26085. --         0 if success
  26086. --        1 if failure
  26087. --
  26088. create proc sp_ivindexhasnullcols (
  26089.     @viewname sysname
  26090.     ,@fhasnullcols bit OUTPUT
  26091. )
  26092. as
  26093. begin
  26094.     declare    @f_ind_unique bit
  26095.             ,@f_ind_clustered bit
  26096.             ,@ivobject_id int
  26097.             ,@indkey int
  26098.             ,@key sysname
  26099.  
  26100.     --
  26101.     -- validate view object
  26102.     --
  26103.     select @ivobject_id = object_id(@viewname)
  26104.             ,@fhasnullcols = 0
  26105.             
  26106.     if (@ivobject_id IS NULL or @ivobject_id = 0)
  26107.     begin
  26108.         raiserror('sp_ivindexhasnullcols(debug): invalid view object [%s]', 16, 1, @viewname)
  26109.         return 1
  26110.     end
  26111.  
  26112.     --
  26113.     -- get the clustered index and validate
  26114.     --
  26115.     select @f_ind_unique = case (status & 2) when 0 then 0 else 1 end
  26116.             ,@f_ind_clustered = case (status & 16) when 0 then 0 else 1 end 
  26117.     from dbo.sysindexes
  26118.     where id = @ivobject_id and indid = 1
  26119.     
  26120.     if (@f_ind_unique != 1) or (@f_ind_clustered != 1)
  26121.     begin
  26122.         raiserror('sp_ivindexhasnullcols(debug): cannot find unique clustered index for the view [%s]', 16, 1, @viewname)
  26123.         return 1
  26124.     end
  26125.     
  26126.     --
  26127.     -- create an enumeration of all the columns that are part of the view index
  26128.     --
  26129.     create table #indcoltab(vindexcol int identity, keyname sysname collate database_default not null)
  26130.     select @indkey = 1
  26131.     while (@indkey <= 16)
  26132.     begin
  26133.         select @key = index_col( @viewname, 1, @indkey )
  26134.         if (@key is null)
  26135.             break
  26136.         else
  26137.             insert into #indcoltab(keyname) values(@key)
  26138.  
  26139.         select @indkey = @indkey + 1
  26140.     end
  26141.  
  26142.     --
  26143.     -- We should not have any column participating in this index
  26144.     -- that allows NULL if we do
  26145.     -- mark the output flag to TRUE
  26146.     --
  26147.     if exists (select * 
  26148.         from dbo.syscolumns 
  26149.         where id = @ivobject_id 
  26150.             and isnullable = 1
  26151.             and name in (select keyname from #indcoltab))
  26152.     begin
  26153.         select @fhasnullcols = 1
  26154.     end
  26155.  
  26156.     --
  26157.     -- all done, cleanup and return
  26158.     --
  26159.     drop table #indcoltab
  26160.     return 0
  26161. end
  26162. go
  26163.  
  26164. EXEC dbo.sp_MS_marksystemobject sp_ivindexhasnullcols
  26165. GO
  26166.  
  26167.  
  26168. --
  26169. -- fn_sqlvarbasetostr
  26170. --
  26171. -- UDF to generate string from a given sqlvariant using its base type.
  26172. -- This function is used by compensating commands and use special rules
  26173. -- for generating strings :
  26174. -- For datatypes - varchar, nvarchar, char, nchar, uniqueidenfier, 
  26175. -- datetime, smalldatetime, invalid date : The value is quoted with single
  26176. -- quotes and any embedded quotes are prefixed with single quote
  26177. -- For other datatypes - The value is not quoted
  26178. -- 
  26179. -- Parameters:
  26180. --    @ssvar sql_variant         input sqlvariant parameter (could be NULL)
  26181. --
  26182. -- Returns:
  26183. --     nvarchar(4000) NULL        generated string. Is NULL if input is NULL
  26184. --
  26185. create function dbo.fn_sqlvarbasetostr (
  26186.     @ssvar sql_variant
  26187. )
  26188. returns nvarchar(4000)
  26189. as
  26190. begin
  26191.     declare @pstrout nvarchar(4000)
  26192.             ,@basetype sysname
  26193.  
  26194.     select @basetype = CAST(SQL_VARIANT_PROPERTY ( @ssvar, 'BaseType' ) as nvarchar(255))
  26195.     if (@ssvar IS NOT NULL and @basetype IS NOT NULL)
  26196.     begin
  26197.         if (lower(@basetype collate SQL_Latin1_General_CP1_CS_AS) = 'varchar')
  26198.             select @pstrout = N'''' + REPLACE(CAST(@ssvar as nvarchar(4000)), '''', '''''') + N''''
  26199.         else if (lower(@basetype collate SQL_Latin1_General_CP1_CS_AS) = 'nvarchar')
  26200.             select @pstrout = N'N''' + REPLACE(CAST(@ssvar as nvarchar(4000)), '''', '''''') + N''''
  26201.         else if (lower(@basetype collate SQL_Latin1_General_CP1_CS_AS) = 'char')
  26202.             select @pstrout = N'''' + REPLACE(RTRIM(CAST(@ssvar as nvarchar(4000))), '''', '''''') + N''''
  26203.         else if (lower(@basetype collate SQL_Latin1_General_CP1_CS_AS) = 'nchar')
  26204.             select @pstrout = N'N''' + REPLACE(RTRIM(CAST(@ssvar as nvarchar(4000))), '''', '''''') + N''''
  26205.         else if (lower(@basetype collate SQL_Latin1_General_CP1_CS_AS) in ('binary','varbinary'))
  26206.             select @pstrout = master.dbo.fn_varbintohexsubstring(1, CAST(@ssvar as varbinary(8000)), 1, 0)
  26207.         else if (lower(@basetype collate SQL_Latin1_General_CP1_CS_AS) in ('bit','bigint','int','smallint','tinyint','float','real','decimal','numeric'))
  26208.             select @pstrout = CAST(@ssvar as nvarchar(40))
  26209.         else if (lower(@basetype collate SQL_Latin1_General_CP1_CS_AS) in ('money','smallmoney'))
  26210.             select @pstrout = CONVERT(nvarchar(40), @ssvar, 2)
  26211.         else if (lower(@basetype collate SQL_Latin1_General_CP1_CS_AS) = 'uniqueidentifier')
  26212.             select @pstrout = N'''' + CAST(@ssvar as nvarchar(40)) + N''''
  26213.         else if (lower(@basetype collate SQL_Latin1_General_CP1_CS_AS) in ('datetime','smalldatetime'))
  26214.             select @pstrout = N'''' + CONVERT(nvarchar(40), @ssvar, 112) + N' ' + CONVERT(nvarchar(40), @ssvar, 114) + N''''
  26215.         else
  26216.             select @pstrout = N'''Invalid Datatype' + lower(@basetype collate SQL_Latin1_General_CP1_CS_AS) + N'(' + CAST(@ssvar as nvarchar) + N')'''
  26217.     end
  26218.  
  26219.     -- All done
  26220.     return @pstrout
  26221. end
  26222. go
  26223. exec dbo.sp_MS_marksystemobject fn_sqlvarbasetostr
  26224. go
  26225.  
  26226. --
  26227. -- sp_replqueuemonitor
  26228. --
  26229. -- Description: this stored procedure displays the messages stored in the 
  26230. --      queue for a given subscription to a queued publication
  26231. --
  26232. -- Parameters:  
  26233. --    1. publisher (sysname, NULL for all publishers)
  26234. --    2. publisherdb (sysname, NULL for all publisherdbs)
  26235. --    3. publication (sysname , NULL for all publications)
  26236. --    4. tranid ( nvarchar(70) NULL for all transactions)
  26237. --      5. queuetype (tinyint 0 for all types of queues, 1 for MSMQ, 2 for SQL)
  26238. --
  26239. -- Results:
  26240. --  Rows of Messages stored in the queue (all types) in the following format:
  26241. --    publisher         sysname,
  26242. --    publisher_db     sysname,
  26243. --    publication     sysname,
  26244. --    tranid             sysname,
  26245. --    commandlen         int,
  26246. --    command         nvarchar(4000)
  26247. -- The command is truncated (less than 4000 characters) if
  26248. --    1. The total rowsize exceeds the maximum of 8060 bytes
  26249. --    2. The SQL command spans multiple queue messages
  26250. -- The queue messages that do not contain SQL command or are part of a spanning
  26251. -- SQL command are not displayed
  26252. --
  26253. -- Returns:
  26254. --         0 if success
  26255. --        1 if failure
  26256. --
  26257. raiserror('Creating procedure sp_replqueuemonitor', 0,1)
  26258. go
  26259. create proc sp_replqueuemonitor (
  26260.     @publisher         sysname = NULL
  26261.     ,@publisherdb     sysname = NULL
  26262.     ,@publication     sysname = NULL
  26263.     ,@tranid             sysname = NULL
  26264.     ,@queuetype        tinyint = 0    -- 0 = All Queues, 1 = MSMQ, 2 = SQL
  26265. )
  26266. as
  26267. begin
  26268.     set nocount on
  26269.     declare @retcode int
  26270.             ,@queue_server sysname
  26271.             ,@queue_id sysname
  26272.             ,@data varbinary(8000)
  26273.             ,@datalen int
  26274.             ,@commandtype int
  26275.             ,@cmdstate bit
  26276.             ,@mesglen int
  26277.             ,@command nvarchar(4000)
  26278.             ,@partialindex int
  26279.             ,@rowlen int
  26280.             ,@comandlen int
  26281.  
  26282.     declare    @k_mesg_partial_state bit
  26283.             ,@k_mesg_complete_state bit
  26284.             ,@k_mesg_tran_cmd int
  26285.             ,@k_max_rowlen int
  26286.             ,@k_queuetype_all tinyint
  26287.             ,@k_queuetype_msmq tinyint
  26288.             ,@k_queuetype_sql tinyint
  26289.  
  26290.     create table #mesgs (mesgid int identity PRIMARY KEY, queuetype tinyint default 1, publisher sysname collate database_default, publisher_db sysname collate database_default, publication sysname collate database_default, 
  26291.                             tranid sysname collate database_default, commandlen int, command ntext)
  26292.  
  26293.     --
  26294.     -- Check if need to look for subscriptions
  26295.     --
  26296.     if exists (select * from dbo.sysobjects where name = 'MSsubscription_agents')
  26297.     begin
  26298.         --
  26299.         -- Are there any qualifying subscriptions
  26300.         --
  26301.         if exists (select * from dbo.MSsubscription_agents where
  26302.                 publisher = case when @publisher is NULL then publisher else UPPER(@publisher) end AND
  26303.                 publisher_db = case when @publisherdb is NULL then publisher_db else @publisherdb end AND
  26304.                 publication = case when @publication is NULL then publication else @publication end )
  26305.         begin
  26306.             --
  26307.             -- initialize
  26308.             --
  26309.             select     @k_queuetype_all = 0
  26310.                     ,@k_queuetype_msmq = 1
  26311.                     ,@k_queuetype_sql = 2
  26312.                     
  26313.             --
  26314.             -- MSMQ based
  26315.             --
  26316.             if (@queuetype in (@k_queuetype_all, @k_queuetype_msmq) and
  26317.                 exists (select * from dbo.MSsubscription_agents where
  26318.                     publisher = case when @publisher is NULL then publisher else UPPER(@publisher) end AND
  26319.                     publisher_db = case when @publisherdb is NULL then publisher_db else @publisherdb end AND
  26320.                     publication = case when @publication is NULL then publication else @publication end  AND
  26321.                     update_mode IN (2,3) AND
  26322.                     queue_id != N'mssqlqueue'))
  26323.             begin
  26324.                 --
  26325.                 -- enumerate each queue
  26326.                 --
  26327.                 create table #queues (publisher sysname collate database_default, publisher_db sysname collate database_default, publication sysname collate database_default, queue_id sysname collate database_default)
  26328.                 declare #htempcursor cursor local for
  26329.                     select publisher, publisher_db, publication, queue_server, queue_id 
  26330.                     from dbo.MSsubscription_agents 
  26331.                     where
  26332.                         publisher = case when @publisher is NULL then publisher else UPPER(@publisher) end AND
  26333.                         publisher_db = case when @publisherdb is NULL then publisher_db else @publisherdb end AND
  26334.                         publication = case when @publication is NULL then publication else @publication end  AND
  26335.                         update_mode IN (2,3) AND
  26336.                         queue_id != N'mssqlqueue'
  26337.  
  26338.                 open #htempcursor
  26339.                 fetch #htempcursor into @publisher, @publisherdb, @publication, @queue_server, @queue_id
  26340.                 while (@@fetch_status = 0)
  26341.                 begin
  26342.                     --
  26343.                     -- add the queue server prefix
  26344.                     --
  26345.                     select @queue_id = N'DIRECT=OS:' + @queue_server + N'\PRIVATE$\' + @queue_id
  26346.                     
  26347.                     --
  26348.                     -- Display all the messages in this queue
  26349.                     --
  26350.                     insert into #mesgs (publisher, publisher_db, publication, tranid, commandlen, command)
  26351.                         exec @retcode = master.dbo.xp_displayqueuemesgs @publisher, @publisherdb, @publication, @queue_id, @tranid
  26352.                     if (@retcode != 0 or @@error != 0)
  26353.                         return 1
  26354.  
  26355.                     --
  26356.                     -- fetch next row
  26357.                     --
  26358.                     fetch #htempcursor into @publisher, @publisherdb, @publication, @queue_server, @queue_id
  26359.                 end
  26360.                 close #htempcursor
  26361.                 deallocate #htempcursor
  26362.     
  26363.                 --
  26364.                 -- All MSMQ Queues processed
  26365.                 --
  26366.                 drop table #queues
  26367.             end
  26368.             
  26369.             --
  26370.             -- SQL Queued based
  26371.             --
  26372.             if (@queuetype in (@k_queuetype_all, @k_queuetype_sql) and
  26373.                 exists (select * from dbo.MSsubscription_agents where
  26374.                     publisher = case when @publisher is NULL then publisher else UPPER(@publisher) end AND
  26375.                     publisher_db = case when @publisherdb is NULL then publisher_db else @publisherdb end AND
  26376.                     publication = case when @publication is NULL then publication else @publication end  AND
  26377.                     update_mode IN (4,5) AND
  26378.                     queue_id = N'mssqlqueue'))
  26379.             begin
  26380.                 --
  26381.                 -- check if we have a queue
  26382.                 --
  26383.                 if exists (select * from dbo.sysobjects where name = 'MSreplication_queue')
  26384.                 begin
  26385.                     --
  26386.                     -- initialize
  26387.                     --
  26388.                     select @mesglen = 0
  26389.                             ,@partialindex = 0
  26390.                             ,@k_mesg_partial_state = 1
  26391.                             ,@k_mesg_complete_state = 0
  26392.                             ,@k_mesg_tran_cmd = 1
  26393.                             ,@k_max_rowlen = 8000
  26394.                     
  26395.                     --
  26396.                     -- select the messages that qualify
  26397.                     --
  26398.                                             
  26399.                     declare #htempcursor cursor local for
  26400.                         select publisher, publisher_db, publication, tranid, datalen, data, commandtype, cmdstate
  26401.                         from dbo.MSreplication_queue 
  26402.                         where
  26403.                             publisher = case when @publisher is NULL then publisher else UPPER(@publisher) end AND
  26404.                             publisher_db = case when @publisherdb is NULL then publisher_db else @publisherdb end AND
  26405.                             publication = case when @publication is NULL then publication else @publication end  AND
  26406.                             tranid = case when @tranid IS NULL then tranid else @tranid end
  26407.                     open #htempcursor
  26408.                     fetch #htempcursor into @publisher, @publisherdb, @publication, @tranid, @datalen, @data, @commandtype, @cmdstate
  26409.                     while (@@fetch_status = 0)
  26410.                     begin
  26411.                         --
  26412.                         -- check the message state
  26413.                         --
  26414.                         if (@cmdstate = @k_mesg_partial_state)
  26415.                             select @partialindex = @partialindex + 1
  26416.                         select @mesglen = @mesglen + @datalen
  26417.  
  26418.                         --
  26419.                         -- process the body only for command type messages
  26420.                         -- and if the command spans multiple rows, then
  26421.                         -- display only the first row
  26422.                         --
  26423.                         if ((@commandtype = @k_mesg_tran_cmd) and
  26424.                             ((@cmdstate = @k_mesg_complete_state and @partialindex = 0) or
  26425.                             (@cmdstate = @k_mesg_partial_state and @partialindex = 1)))
  26426.                         begin
  26427.                             --
  26428.                             -- decode the command
  26429.                             --
  26430.                             exec @retcode = master.dbo.xp_decodequeuecmd @data, @command OUTPUT
  26431.                             if (@retcode != 0 or @@error != 0)
  26432.                                 return 1
  26433.                         end
  26434.                         
  26435.                         --
  26436.                         -- Are processing the final row for this command
  26437.                         --
  26438.                         if (@cmdstate = @k_mesg_complete_state)
  26439.                         begin
  26440.                             --
  26441.                             -- reset partial index
  26442.                             --
  26443.                             if (@partialindex > 0)
  26444.                                 select @partialindex = 0
  26445.  
  26446.                             if (@command IS NOT NULL)
  26447.                             begin
  26448.                                 --
  26449.                                 -- check if the command needs to truncated to fit the max rowsize
  26450.                                 --
  26451.                                 select @rowlen = 4 + DATALENGTH(@k_queuetype_sql) + 
  26452.                                                  DATALENGTH(@publisher) + DATALENGTH(@publisherdb) +
  26453.                                                  DATALENGTH(@publication) + DATALENGTH(@tranid) + 
  26454.                                                  DATALENGTH(@mesglen)
  26455.                                         ,@comandlen = DATALENGTH(@command)
  26456.                                 if (@rowlen + @comandlen > @k_max_rowlen)
  26457.                                 begin
  26458.                                     select @comandlen = @k_max_rowlen - @rowlen
  26459.                                     select @comandlen = @comandlen / 2
  26460.                                     select @command = SUBSTRING(@command, 1, @comandlen)
  26461.                                 end
  26462.                                 
  26463.                                 insert into #mesgs (queuetype, publisher, publisher_db, publication, tranid, commandlen, command)
  26464.                                 values (@k_queuetype_sql, @publisher, @publisherdb, @publication, @tranid, @mesglen, @command)
  26465.                                 if (@retcode != 0 or @@error != 0)
  26466.                                     return 1
  26467.  
  26468.                                 select @command = NULL
  26469.                             end
  26470.  
  26471.                             --
  26472.                             -- reset command len
  26473.                             --
  26474.                             if (@mesglen > 0)
  26475.                                 select @mesglen = 0
  26476.                         end
  26477.                         
  26478.                         --
  26479.                         -- fetch next row
  26480.                         --
  26481.                         fetch #htempcursor into @publisher, @publisherdb, @publication, @tranid, @datalen, @data, @commandtype, @cmdstate
  26482.                     end
  26483.                     close #htempcursor
  26484.                     deallocate #htempcursor
  26485.                 end 
  26486.     
  26487.                 --
  26488.                 -- All SQL Queues processed
  26489.                 --
  26490.             end
  26491.         end
  26492.     end
  26493.     
  26494.     --
  26495.     -- return result
  26496.     --
  26497.     select     queue = case when queuetype = @k_queuetype_msmq then N'MSMQ'
  26498.                         when queuetype = @k_queuetype_sql then N'SQLQ' end 
  26499.             ,publisher
  26500.             ,publisher_db
  26501.             ,publication
  26502.             ,tranid
  26503.             ,commandlen
  26504.             ,command 
  26505.     from #mesgs
  26506.     order by mesgid
  26507.     
  26508.     --
  26509.     -- All done
  26510.     --
  26511.     drop table #mesgs
  26512.     return 0
  26513. end
  26514. go
  26515. exec dbo.sp_MS_marksystemobject sp_replqueuemonitor
  26516. go
  26517.  
  26518. --
  26519. -- sp_replsqlqgetrows
  26520. --
  26521. -- Description: this stored procedure returns the queued data stored in the 
  26522. --     MSreplication_queue for a specific subscription to a queued publication.
  26523. --    This SP is used by Queue Reader Agent to service SQL based Queues.
  26524. --
  26525. -- Parameters:  
  26526. --    1. publisher         (sysname, NOT NULL)
  26527. --    2. publisherdb     (sysname, NOT NULL)
  26528. --    3. publication     (sysname, NOT NULL)
  26529. --
  26530. -- Results:
  26531. --  Rows of Queued Data stored in MSreplication_queue in the following format:
  26532. --    tranid                sysname
  26533. --    datalen                int
  26534. --    data                image
  26535. --    commandtype            int
  26536. --    insertdate            datetime
  26537. --    orderkey            bigint
  26538. --    cmdstate            bit
  26539. --
  26540. -- Returns:
  26541. --         0 if success
  26542. --        1 if failure
  26543. --
  26544. raiserror('Creating procedure sp_replsqlqgetrows', 0,1)
  26545. go
  26546. create proc sp_replsqlqgetrows (
  26547.     @publisher         sysname
  26548.     ,@publisherdb     sysname
  26549.     ,@publication     sysname
  26550. )
  26551. as
  26552. begin
  26553.     set nocount on
  26554.     
  26555.     --
  26556.     -- return rows
  26557.     --
  26558.     if exists (select * from dbo.sysobjects where name = 'MSreplication_queue')
  26559.     begin
  26560.         select tranid, datalen, data, commandtype, insertdate, orderkey, cmdstate 
  26561.         from dbo.MSreplication_queue with (READPAST) 
  26562.         where UPPER(publisher) = UPPER(@publisher) 
  26563.             and publisher_db = @publisherdb 
  26564.             and publication = @publication
  26565.         order by orderkey, tranid 
  26566.  
  26567.         if (@@error != 0)
  26568.             return 1
  26569.     end
  26570.     else
  26571.     begin
  26572.         --
  26573.         -- create empty rowset
  26574.         --
  26575.         declare @nomesgs TABLE (tranid     sysname, datalen int, data varbinary(8000),
  26576.             commandtype int, insertdate datetime, orderkey bigint, cmdstate bit)
  26577.         select * from @nomesgs
  26578.     end
  26579.     
  26580.     --
  26581.     -- All done
  26582.     --
  26583.     return 0
  26584. end
  26585. go
  26586. exec dbo.sp_MS_marksystemobject sp_replsqlqgetrows
  26587. go
  26588. --
  26589. -- sp_MSpost_auto_proc
  26590. --
  26591. -- Description: Helper store proc, used by schema replication.
  26592. --        Scripts out custom proc generation code and post to the log.
  26593. --
  26594. -- Returns:
  26595. --         0 if success
  26596. --        1 if failure
  26597. --
  26598. raiserror('Creating procedure sp_MSpost_auto_proc', 0,1)
  26599. go
  26600. create proc sp_MSpost_auto_proc 
  26601.         @pubid int, 
  26602.         @artid int, 
  26603.         @procname nvarchar(128)
  26604. as
  26605. begin
  26606.     declare @proctext nvarchar(4000)
  26607.     declare @retcode int
  26608.     
  26609.     set nocount on
  26610.     select @retcode = 0
  26611.     
  26612.     /*
  26613.     ** Security Check
  26614.     */
  26615.     exec @retcode = dbo.sp_MSreplcheck_publish
  26616.     if @@ERROR <> 0 or @retcode <> 0
  26617.         return(1)
  26618.  
  26619.     -- save the geneartion code
  26620.     create table #temptext (colidx int identity, col nvarchar(4000) collate database_default)
  26621.     insert #temptext (col) exec @procname @artid
  26622.     
  26623.     -- post to the log
  26624.     declare #trancolumn CURSOR LOCAL FAST_FORWARD for 
  26625.         select col from #temptext order by colidx
  26626.     open #trancolumn
  26627.     fetch #trancolumn into @proctext
  26628.     while (@@fetch_status <> -1)
  26629.     BEGIN
  26630.         if(@proctext = N'go') -- post the drop as one command
  26631.         begin
  26632.             exec @retcode = sp_replpostcmd 0, @pubid, @artid, 35, N' -- '
  26633.             if(@retcode <> 0) or (@@error <> 0)
  26634.                 return 1
  26635.         end
  26636.         else
  26637.         begin
  26638.             select @proctext = @proctext + N' '
  26639.             exec @retcode = sp_replpostcmd 1, @pubid, @artid, 35, @proctext
  26640.             if(@retcode <> 0) or (@@error <> 0)
  26641.                 return 1
  26642.         end
  26643.         fetch #trancolumn into @proctext
  26644.     END
  26645.     exec @retcode = sp_replpostcmd 0, @pubid, @artid, 35, N' --'
  26646.     if(@retcode <> 0) or (@@error <> 0)
  26647.         return 1
  26648.     close #trancolumn
  26649.     deallocate #trancolumn
  26650.     return 0
  26651. end
  26652. go
  26653. EXEC dbo.sp_MS_marksystemobject sp_MSpost_auto_proc
  26654. go
  26655. --
  26656. -- sp_MSrepl_schema 
  26657. --
  26658. -- Description: Helper store proc, used by schema replication.
  26659. --        constructs schema modification code and post to the log.
  26660. --
  26661. -- Returns:
  26662. --         0 if success
  26663. --        1 if failure
  26664. --
  26665. raiserror('Creating procedure sp_MSrepl_schema', 0,1)
  26666. go
  26667.  
  26668. create proc sp_MSrepl_schema @pubname sysname
  26669.                 ,@artid int 
  26670.                 ,@qual_source_object nvarchar(362) -- quoted table name
  26671.                 ,@column sysname -- column name, not quoted, as we need to search in syscolumns by it.
  26672.                 ,@operation int -- 0 is add, 1 is drop
  26673.                 ,@typetext nvarchar(3000) = NULL    
  26674.                 ,@schema_change_script nvarchar(4000) = NULL
  26675. as
  26676. begin
  26677.     declare @retcode int
  26678.     declare @pubid int
  26679.     declare @objid int
  26680.     declare @schema_option binary(8)
  26681.     declare @auto_gen int
  26682.     declare @cmd_type int
  26683.     declare @ins_cmd nvarchar(510)
  26684.     declare @del_cmd nvarchar(510)
  26685.     declare @upd_cmd nvarchar(510)
  26686.     declare @repub_command nvarchar(4000)
  26687.     declare @nopub_command nvarchar(4000)
  26688.     declare @prefix nvarchar(32)
  26689.     declare @post_cmd nvarchar(4000)
  26690.     declare @qual_column sysname
  26691.     declare @use_script bit
  26692.     declare @allow_dts bit
  26693.     
  26694.     set nocount on
  26695.     select @retcode = 0
  26696.     select @auto_gen = 2 -- auto generate custom procs
  26697.     select @cmd_type = 35 -- SQL statement
  26698.     select @qual_column = QUOTENAME(@column)
  26699.     select @objid = object_id(@qual_source_object)
  26700.  
  26701.     /*
  26702.     ** Security Check
  26703.     */
  26704.     exec @retcode = dbo.sp_MSreplcheck_publish
  26705.     if @@ERROR <> 0 or @retcode <> 0
  26706.         return(1)
  26707.  
  26708.     if (@schema_change_script is not NULL) and (len(@schema_change_script) > 0)
  26709.         select @use_script = 1
  26710.     else
  26711.         select @use_script = 0
  26712.     
  26713.     
  26714.     select @pubid = a.pubid, @schema_option = schema_option, @ins_cmd = ins_cmd, @del_cmd = del_cmd, @upd_cmd = upd_cmd, @allow_dts = allow_dts 
  26715.         from sysarticles a join syspublications p on a.pubid = p.pubid where artid = @artid
  26716.     
  26717.     if (@allow_dts = 1)
  26718.         goto SCRIPTONLY
  26719.  
  26720.     if(@operation = 0)
  26721.     begin
  26722.         select @repub_command = N'exec sp_repladdcolumn @source_object=N''' + @qual_source_object + N''',@column=N''' + replace(@column  , N'''', N'''''')
  26723.                         + N''',@typetext=N''' + replace(@typetext, N'''', N'''''') + N''' '
  26724.         select @nopub_command = N'else alter table ' + @qual_source_object + N' add ' + @qual_column + N' ' + @typetext + N' ' 
  26725.         select @prefix = N'if not exists '
  26726.     end
  26727.     else
  26728.     begin
  26729.         select @repub_command = N'exec sp_repldropcolumn @source_object=N''' + @qual_source_object + N''',@column=N''' + @column  + N''' '
  26730.         select @nopub_command = N'else alter table ' + @qual_source_object + N' drop column ' + @qual_column + N' '
  26731.         select @prefix = N'if exists '
  26732.     end
  26733.     if (@use_script = 1)--Need to pass the script file along if sub is republished.
  26734.         select @repub_command = @repub_command  + N',@schema_change_script=N''' + @schema_change_script + N''' '
  26735.     select @post_cmd = @prefix + N'(select * from syscolumns where name=''' + @column + ''' and id = object_id('''+ PARSENAME(@qual_source_object, 1) + ''')) begin '
  26736.     exec @retcode = sp_replpostcmd 1, @pubid, @artid, @cmd_type, @post_cmd 
  26737.     if(@retcode <> 0) or (@@error <> 0)
  26738.         return 1
  26739.     select @post_cmd = N'if exists (select * from sysobjects where name=''syspublications'') if exists (select * from sysarticles where objid=object_id('''+ PARSENAME(@qual_source_object, 1) + ''')) and @@microsoftversion >= 0x07320000 '
  26740.     exec @retcode = sp_replpostcmd 1, @pubid, @artid, @cmd_type, @post_cmd 
  26741.     if(@retcode <> 0) or (@@error <> 0)
  26742.         return 1
  26743.     exec @retcode = sp_replpostcmd 1, @pubid, @artid, @cmd_type, @repub_command
  26744.     if(@retcode <> 0) or (@@error <> 0)
  26745.         return 1
  26746.     exec @retcode = sp_replpostcmd 1, @pubid, @artid, @cmd_type, @nopub_command
  26747.     if(@retcode <> 0) or (@@error <> 0)
  26748.         return 1
  26749.     exec @retcode = sp_replpostcmd 1, @pubid, @artid, @cmd_type, @nopub_command
  26750.     if(@retcode <> 0) or (@@error <> 0)
  26751.         return 1
  26752.     exec @retcode = sp_replpostcmd 0, @pubid, @artid, @cmd_type, N' end '
  26753.     if(@retcode <> 0) or (@@error <> 0)
  26754.         return 1
  26755.     
  26756.     if ((convert(int, @schema_option) & @auto_gen) > 0)-- No script, but custom procs were auto-generated
  26757.     begin
  26758.         if(UPPER(LEFT(LTRIM(@ins_cmd), 4) collate SQL_Latin1_General_CP1_CS_AS) = UPPER('CALL' collate SQL_Latin1_General_CP1_CS_AS))
  26759.         begin
  26760.             exec @retcode = sp_MSpost_auto_proc @pubid, @artid, 'sp_scriptinsproc' 
  26761.             if(@retcode <> 0) or (@@error <> 0)
  26762.                 return 1
  26763.         end
  26764.         if(UPPER(LEFT(LTRIM(@del_cmd), 4) collate SQL_Latin1_General_CP1_CS_AS) = UPPER('CALL' collate SQL_Latin1_General_CP1_CS_AS))
  26765.         begin
  26766.             exec @retcode = sp_MSpost_auto_proc @pubid, @artid, 'sp_scriptdelproc' 
  26767.             if(@retcode <> 0) or (@@error <> 0)
  26768.                 return 1
  26769.         end
  26770.         else if(UPPER(LEFT(LTRIM(@del_cmd), 5) collate SQL_Latin1_General_CP1_CS_AS) = UPPER('XCALL' collate SQL_Latin1_General_CP1_CS_AS))
  26771.         begin
  26772.             exec @retcode = sp_MSpost_auto_proc @pubid, @artid, 'sp_scriptxdelproc' 
  26773.             if(@retcode <> 0) or (@@error <> 0)
  26774.                 return 1
  26775.         end
  26776.         if(UPPER(LEFT(LTRIM(@upd_cmd), 4) collate SQL_Latin1_General_CP1_CS_AS) = UPPER('CALL' collate SQL_Latin1_General_CP1_CS_AS))
  26777.         begin
  26778.             exec @retcode = sp_MSpost_auto_proc @pubid, @artid, 'sp_scriptupdproc' 
  26779.             if(@retcode <> 0) or (@@error <> 0)
  26780.                 return 1
  26781.         end
  26782.         else if(UPPER(LEFT(LTRIM(@upd_cmd), 5) collate SQL_Latin1_General_CP1_CS_AS) = UPPER('MCALL' collate SQL_Latin1_General_CP1_CS_AS))
  26783.         begin
  26784.             exec @retcode = sp_MSpost_auto_proc @pubid, @artid, 'sp_scriptmappedupdproc' 
  26785.             if(@retcode <> 0) or (@@error <> 0)
  26786.                 return 1
  26787.         end
  26788.         else if(UPPER(LEFT(LTRIM(@upd_cmd), 5) collate SQL_Latin1_General_CP1_CS_AS) = UPPER('XCALL' collate SQL_Latin1_General_CP1_CS_AS))
  26789.         begin
  26790.             exec @retcode = sp_MSpost_auto_proc @pubid, @artid, 'sp_scriptxupdproc' 
  26791.             if(@retcode <> 0) or (@@error <> 0)
  26792.                 return 1
  26793.         end
  26794.     end
  26795. SCRIPTONLY:
  26796.  
  26797.     if (@use_script = 1)
  26798.     begin
  26799.         exec @retcode = sp_addscriptexec @publication = @pubname, @scriptfile = @schema_change_script
  26800.         if @retcode<>0 or @@ERROR<>0
  26801.             return 1
  26802.     end 
  26803.     return 0
  26804. end
  26805. go
  26806. EXEC dbo.sp_MS_marksystemobject sp_MSrepl_schema 
  26807. go
  26808. --
  26809. -- sp_MSreplupdateschema
  26810. --
  26811. -- Description: Wrapper store proc, check for admin\dbowner credential before invoking sp_replupdateschema
  26812. --
  26813. -- Returns:
  26814. --         0 if success
  26815. --        1 if failure
  26816. --
  26817. raiserror('Creating procedure sp_MSreplupdateschema', 0,1)
  26818. go
  26819.  
  26820. create proc sp_MSreplupdateschema  @object_name sysname
  26821. as
  26822. begin
  26823.     declare @retcode int
  26824.     IF @object_name IS NULL
  26825.     BEGIN
  26826.         RAISERROR (14043, 16, -1, '@object_name')
  26827.         RETURN (1)
  26828.     END
  26829.  
  26830.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  26831.     IF @@ERROR <> 0 or @retcode <> 0
  26832.             return (1)
  26833.  
  26834.     exec dbo.sp_replupdateschema @object_name
  26835.     return 0
  26836. end
  26837. go
  26838. EXEC dbo.sp_MS_marksystemobject sp_MSreplupdateschema
  26839. go
  26840. --
  26841. -- sp_MSdefer_check
  26842. --
  26843. -- Description: disable constraints (Foreign Key and Check) and triggers during concurrent snapshot
  26844. --        and script enable cmds for later
  26845. --
  26846. -- Note:     this stored procedure loops through the list of Foreign Key, Check constraints and Triggers
  26847. --        which are not disabled and not marked 'not for replicaiton', it uses 'alter table' to disable 
  26848. --        these entries (nocheck/disable), and copies the corresponding enable code into a temp table.
  26849. --        at the end, cmds in temp table is used to build a stored procedure which will be used by dist 
  26850. --        agent to enable these cnst/triggers at the end of concurrent snapshot. if it failed to create 
  26851. --        the stored procedure, a default one (sp_MSreenable_check) will be used, the key difference here
  26852. --        is the sp created here will only enable the ones we disabled here, while the default one will 
  26853. --        enable all in current table.
  26854. --
  26855. --        the sp created within sp_MSdefer_check will enable all the entries disabled by sp_MSdefer_check, 
  26856. --        then drop itself at the end.
  26857. --
  26858. -- Returns:
  26859. --         0 if success
  26860. --        1 if failure
  26861. --
  26862. raiserror('Creating procedure sp_MSdefer_check', 0,1)
  26863. go
  26864. create proc sp_MSdefer_check @objname sysname, @objowner sysname = NULL
  26865. as
  26866.     set nocount on
  26867.     declare @cnstname sysname
  26868.     declare @cnstid int
  26869.     declare @objid int
  26870.     declare @enable_cmd nvarchar(4000)
  26871.     declare @disable_cmd nvarchar(4000)
  26872.     declare @quotedproc nvarchar(240)
  26873.     declare @dest nvarchar(514)
  26874.     declare @dbname sysname
  26875.     declare @proc_exists bit
  26876.  
  26877.     if(@objowner is not null)
  26878.         select @dest = quotename(@objowner) + N'.' + quotename(@objname)
  26879.     else
  26880.         select @dest = quotename(@objname)
  26881.  
  26882.     declare @retcode int
  26883.     IF @objname IS NULL
  26884.     BEGIN
  26885.         RAISERROR (14043, 16, -1, '@objname')
  26886.         RETURN (1)
  26887.     END
  26888.  
  26889.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  26890.     IF @@ERROR <> 0 or @retcode <> 0
  26891.             return (1)
  26892.  
  26893.     select @objid = object_id(@dest)
  26894.     select @enable_cmd = N'sp_MSenable_' + convert(varchar(64), @objid)
  26895.     if exists(select name from sysobjects where name = @enable_cmd and ObjectProperty(id, 'IsProcedure') = 1)
  26896.         select @proc_exists = 1
  26897.     else
  26898.         select @proc_exists = 0
  26899.  
  26900.     select @quotedproc = quotename(@enable_cmd)
  26901.     select @enable_cmd = N'create proc ' + @quotedproc + N' as '
  26902.     create table ##proccmd (c1 int identity, c2 nvarchar(3000) collate database_default)
  26903.     insert ##proccmd (c2) values (@enable_cmd)
  26904.     
  26905.     declare ms_crs_cnst cursor local static for
  26906.     select name, id from sysobjects where parent_obj = @objid and 
  26907.            ((OBJECTPROPERTY(id, 'CnstIsDisabled') = 0 and OBJECTPROPERTY(id, 'CnstIsNotRepl') = 0 and 
  26908.             (OBJECTPROPERTY(id, 'IsCheckCnst') = 1 or OBJECTPROPERTY(id, 'IsForeignKey') = 1))
  26909.         or (ObjectProperty(id, 'IsTrigger') = 1 and OBJECTPROPERTY(id, 'ExecIsTriggerNotForRepl') = 0 and ObjectProperty(id, 'ExecIsTriggerDisabled') = 0))
  26910.     for read only
  26911.  
  26912.     open ms_crs_cnst
  26913.     fetch ms_crs_cnst into @cnstname, @cnstid
  26914.     while @@fetch_status >= 0
  26915.     begin
  26916.         if(ObjectProperty(@cnstid, 'IsTrigger') = 1)
  26917.         begin
  26918.             select @disable_cmd = N'alter table ' + @dest + N' disable trigger ' + quotename(@cnstname)
  26919.             select @enable_cmd = N'alter table ' + @dest + N' enable trigger '+quotename(@cnstname)
  26920.         end
  26921.         else
  26922.         begin
  26923.             select @disable_cmd = N'alter table ' + @dest + N' nocheck constraint ' + quotename(@cnstname)
  26924.             select @enable_cmd = N'alter table ' + @dest + N' check constraint ' + quotename(@cnstname)
  26925.         end
  26926.         insert ##proccmd (c2) values (@enable_cmd)
  26927.  
  26928.         execute(@disable_cmd)
  26929.         fetch ms_crs_cnst into @cnstname, @cnstid
  26930.     end        --of major loop
  26931.     deallocate ms_crs_cnst
  26932.     if(@proc_exists = 1) -- don't try to recreate the proc
  26933.     begin 
  26934.         select N'exec ' + @quotedproc
  26935.         drop table ##proccmd
  26936.         return 0
  26937.     end
  26938.  
  26939.     select @enable_cmd = N'drop proc ' + @quotedproc
  26940.     insert ##proccmd (c2) values (@enable_cmd)
  26941.     select @enable_cmd = N'select c2 from ##proccmd order by c1'
  26942.     select @dbname = db_name()
  26943.     exec @retcode = master..xp_execresultset @enable_cmd, @dbname
  26944.     if @@error <> 0 or @retcode <> 0 or @quotedproc is NULL
  26945.     begin
  26946.         declare @cmd_param nvarchar(4000)
  26947.         if (@objowner is null)
  26948.             select @cmd_param = N' @objname = N''' + @objname + N''''
  26949.         else
  26950.             select @cmd_param = N' @objname = N''' + @objname + N''', @objowner = N''' + @objowner + N''''
  26951.         select N'exec sp_MSreenable_check ' + @cmd_param
  26952.     end
  26953.     else
  26954.         select N'exec ' + @quotedproc
  26955.     drop table ##proccmd
  26956.     return 0
  26957. go
  26958. EXEC dbo.sp_MS_marksystemobject sp_MSdefer_check
  26959. go
  26960. --
  26961. -- sp_MSreenable_check
  26962. --
  26963. -- Description: default sp to enable constraints (Foreign Key and Check) and triggers at 
  26964. --        the end of compensation mode in concurrent snapshot.
  26965. --
  26966. -- Note :     this default sp doesn't get used unless we failed to construct a temp one at runtime.
  26967. --
  26968. -- Returns:
  26969. --         0 if success
  26970. --        1 if failure
  26971. --
  26972. raiserror('Creating procedure sp_MSreenable_check', 0,1)
  26973. go
  26974. create proc sp_MSreenable_check @objname sysname, @objowner sysname = NULL
  26975. as
  26976.     set nocount on
  26977.     
  26978.     declare @cnstname sysname
  26979.     declare @cnstid int
  26980.     declare @objid int
  26981.     declare @enable_cmd nvarchar(4000)
  26982.     declare @dest nvarchar(514)
  26983.  
  26984.     declare @retcode int
  26985.     IF @objname IS NULL
  26986.     BEGIN
  26987.         RAISERROR (14043, 16, -1, '@objname')
  26988.         RETURN (1)
  26989.     END
  26990.  
  26991.     if(@objowner is not null)
  26992.         select @dest = quotename(@objowner) + N'.' + quotename(@objname)
  26993.     else
  26994.         select @dest = quotename(@objname)
  26995.  
  26996.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  26997.     IF @@ERROR <> 0 or @retcode <> 0
  26998.             return (1)
  26999.  
  27000.     select @objid = object_id(@objname)
  27001.     
  27002.     declare ms_crs_cnst cursor local static for
  27003.     select name, id from sysobjects where parent_obj = @objid and 
  27004.            ((OBJECTPROPERTY(id, 'CnstIsDisabled') = 1 and OBJECTPROPERTY(id, 'CnstIsNotRepl') = 0 and 
  27005.             (OBJECTPROPERTY(id, 'IsCheckCnst') = 1 or OBJECTPROPERTY(id, 'IsForeignKey') = 1))
  27006.         or (ObjectProperty(id, 'IsTrigger') = 1 and OBJECTPROPERTY(id, 'ExecIsTriggerNotForRepl') = 0 and ObjectProperty(id, 'ExecIsTriggerDisabled') = 1))
  27007.     for read only
  27008.  
  27009.     open ms_crs_cnst
  27010.     fetch ms_crs_cnst into @cnstname, @cnstid
  27011.     while @@fetch_status >= 0
  27012.     begin
  27013.         if(ObjectProperty(@cnstid, 'IsTrigger') = 1)
  27014.             select @enable_cmd = N'alter table ' + @dest + N' enable trigger ' + quotename(@cnstname)
  27015.         else
  27016.             select @enable_cmd = N'alter table ' + @dest + N' check constraint ' + quotename(@cnstname)
  27017.  
  27018.         execute(@enable_cmd)
  27019.         fetch ms_crs_cnst into @cnstname, @cnstid
  27020.     end        --of major loop
  27021.     deallocate ms_crs_cnst
  27022.     return 0
  27023. go
  27024. EXEC dbo.sp_MS_marksystemobject sp_MSreenable_check
  27025. go
  27026.  
  27027. --
  27028. -- sp_getqueuedrows
  27029. --
  27030. -- sp_getqueuedrows is invoked by user to find the rows of given table on
  27031. -- a subscriber database that have participated in a queued update and 
  27032. -- currently have not been resolved by the queue reader agent - i.e. current
  27033. -- have an outstanding queued transaction. The table has to be part of 
  27034. -- queued subscription.
  27035. -- 
  27036. -- Parameters
  27037. --     @tablename    sysname -- name of table
  27038. --    @user        sysname -- optional name of user
  27039. --    @tranid        nvarchar(70) -- optional tranid to filter results on
  27040. --
  27041. -- Returns
  27042. --    0 if success 
  27043. --    1 if failure
  27044. --
  27045. -- Resultset
  27046. --     Rows that currently have at least one queued transaction for this
  27047. --    subscribed table
  27048. --
  27049. raiserror('Creating procedure sp_getqueuedrows', 0,1)
  27050. go
  27051. create proc sp_getqueuedrows (
  27052.     @tablename sysname
  27053.     ,@owner sysname = NULL
  27054.     ,@tranid nvarchar(70) = NULL
  27055. )
  27056. as
  27057. begin
  27058.     set nocount on
  27059.     declare @retcode int
  27060.         ,@dbname sysname
  27061.         ,@qualified_tabname nvarchar(1000)
  27062.         ,@tabid int
  27063.         ,@agent_id int
  27064.         ,@publisher sysname
  27065.         ,@publisher_db sysname
  27066.         ,@publication sysname
  27067.         ,@queue_id sysname
  27068.         ,@update_mode int
  27069.         ,@failover_id int
  27070.         ,@cmd nvarchar(4000)
  27071.         ,@queue_server sysname
  27072.         ,@indid int
  27073.         ,@indkey int
  27074.         ,@key sysname
  27075.         ,@colid int
  27076.         ,@typestring nvarchar(4000)
  27077.         ,@artcol int
  27078.         ,@xpinputstr nvarchar(4000)
  27079.         ,@selectcl nvarchar(4000)
  27080.         ,@joincl nvarchar(4000)
  27081.  
  27082.     --
  27083.     -- prepare the fully qualified table
  27084.     --
  27085.     select @owner = case when (@owner IS NULL) then N'dbo' else @owner end
  27086.             ,@dbname = db_name()    
  27087.     select @qualified_tabname = quotename(@dbname) + N'.' 
  27088.                     + quotename(@owner) + N'.' + quotename(@tablename)
  27089.     select @tabid = object_id(@qualified_tabname)
  27090.     if (@tabid IS NULL) or (@tabid = 0)
  27091.     begin
  27092.         -- error
  27093.         raiserror('sp_getqueuedrows(debug): could not locate table %s', 16, 1, @qualified_tabname)
  27094.         return 1
  27095.     end
  27096.  
  27097.     --
  27098.     -- current user should have SELECT permission on the table
  27099.     --
  27100.     if ( permissions(@tabid) & 0x1 = 0 )
  27101.     begin
  27102.         -- error
  27103.         raiserror('sp_getqueuedrows(debug): current user does not have SELECT permission on table %s', 16, 1, @qualified_tabname)
  27104.         return 1
  27105.     end
  27106.  
  27107.     --
  27108.     -- make sure the table is participating in a active queued subscription
  27109.     --
  27110.     select @agent_id = agent_id 
  27111.     from dbo.MSsubscription_articles 
  27112.     where dest_table = @tablename and owner = @owner
  27113.  
  27114.     if (@agent_id IS NULL)
  27115.     begin
  27116.         -- error
  27117.         raiserror('sp_getqueuedrows(debug): table %s is not part of any active initialized queued subscription. Make sure your queued subscriptions are properly initialized', 16, 1, @qualified_tabname)
  27118.         return 1
  27119.     end
  27120.  
  27121.     --
  27122.     -- get the details for the subscription
  27123.     --
  27124.     select @publisher = publisher
  27125.             ,@publisher_db = publisher_db
  27126.             ,@publication = publication
  27127.             ,@update_mode = update_mode
  27128.             ,@queue_server = queue_server
  27129.             ,@queue_id = queue_id
  27130.             ,@failover_id = failover_mode
  27131.     from dbo.MSsubscription_agents where id = @agent_id
  27132.     if (@update_mode not in (2,3,4,5))
  27133.     begin
  27134.         -- error
  27135.         raiserror('sp_getqueuedrows(debug): table %s is not part of any active initialized queued subscription. Make sure your queued subscriptions are properly initialized', 16, 2, @qualified_tabname)
  27136.         return 1
  27137.     end
  27138.     
  27139.     --
  27140.     -- If we are in Immediate Failover mode - no queued messages
  27141.     --
  27142.     if (@update_mode in (3,5) and (@failover_id = 0))
  27143.     begin
  27144.         --
  27145.         -- do an empty select on the source table and return
  27146.         --
  27147.         select @cmd = N'declare @dummy_action nvarchar(10), @dummy_tranid nvarchar(70)
  27148.                     select action=@dummy_action, tranid=@dummy_tranid, * from ' + 
  27149.                     @qualified_tabname + N' where 1 = 2 '
  27150.         exec (@cmd)
  27151.         return 0
  27152.     end
  27153.  
  27154.     if (@update_mode in (2,3))
  27155.     begin
  27156.         --
  27157.         -- set queue prefix for MSMQ cases
  27158.         --
  27159.         select @queue_id = N'DIRECT=OS:' + @queue_server + N'\PRIVATE$\' + @queue_id
  27160.     end
  27161.     else
  27162.     begin
  27163.         --
  27164.         -- Check the queue table for SQLQ
  27165.         --
  27166.         if not exists (select * from dbo.MSreplication_queue
  27167.         where UPPER(publisher) = UPPER(@publisher) and
  27168.                 publisher_db = @publisher_db and
  27169.                 publication = @publication and
  27170.                 tranid = case when @tranid IS NULL then tranid else @tranid end)
  27171.         begin
  27172.             --
  27173.             -- do an empty select on the source table and return
  27174.             --
  27175.             select @cmd = N'declare @dummy_action nvarchar(10), @dummy_tranid nvarchar(70)
  27176.                     select action=@dummy_action, tranid=@dummy_tranid, * from ' + 
  27177.                     @qualified_tabname + N' where 1 = 2 '
  27178.             exec (@cmd)
  27179.             return 0
  27180.         end
  27181.     end
  27182.  
  27183.     --
  27184.     -- Now find the PK columns for this table
  27185.     --
  27186.     select @indkey = 1
  27187.         ,@artcol = 0
  27188.         ,@xpinputstr = N''
  27189.         ,@selectcl = N''
  27190.         ,@joincl = N''
  27191.         ,@retcode = 0
  27192.  
  27193.     select @indid = i.indid 
  27194.     from dbo.sysindexes i 
  27195.     where ((i.status & 2048) != 0) and (i.id = @tabid)
  27196.     if (@indid is null)
  27197.     begin
  27198.         raiserror('sp_getqueuedrows(debug): Cannot find primary key for %s', 
  27199.                 16, -1, @qualified_tabname)
  27200.         return 1
  27201.     end
  27202.     
  27203.     --
  27204.     -- create an enumeration of all the columns that are part of PK
  27205.     --
  27206.     create table #pkcoltab(pkindex int identity, keyname sysname collate database_default not null)
  27207.     while (@indkey <= 16)
  27208.     begin
  27209.         select @key = index_col( @qualified_tabname, @indid, @indkey )
  27210.         if (@key is null)
  27211.             break
  27212.         else
  27213.             insert into #pkcoltab(keyname) values(@key)
  27214.  
  27215.         select @indkey = @indkey + 1
  27216.     end
  27217.  
  27218.     --
  27219.     -- initialize the commands that we need to build
  27220.     --
  27221.     if exists (select * from dbo.sysobjects where name = 'tempcrtcmd')
  27222.         drop table tempcrtcmd
  27223.     create table tempcrtcmd (c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL)
  27224.     
  27225.     select @cmd = N'create table tempqjointab (action nvarchar(10), tranid nvarchar(70) '
  27226.     insert into tempcrtcmd(procedure_text) values(@cmd)
  27227.  
  27228.     --
  27229.     -- now walk through each article col and if it is
  27230.     -- a part of PK, then check find the column position of the key
  27231.     -- corresponding to any article column is set
  27232.     --
  27233.     DECLARE #hCColid CURSOR LOCAL FAST_FORWARD FOR 
  27234.         select colid, [name] from dbo.syscolumns 
  27235.         where id = @tabid order by colid asc
  27236.  
  27237.     OPEN #hCColid
  27238.     FETCH #hCColid INTO @colid, @key
  27239.     WHILE (@@fetch_status != -1)
  27240.     begin
  27241.         exec sp_MSget_type @tabid, @colid, NULL, @typestring output
  27242.         if ((@typestring IS NOT NULL) and (@typestring != N'timestamp'))
  27243.         begin
  27244.             --
  27245.             -- this column is part of the article
  27246.             --
  27247.             select @artcol = @artcol + 1
  27248.             if exists (select * from #pkcoltab where keyname = @key)
  27249.             begin
  27250.                 --
  27251.                 -- this column is part of PK (offset and precision, scale)
  27252.                 -- prepare the input string for XP
  27253.                 -- prepare the create join table command
  27254.                 -- prepare the join and select clause for the result
  27255.                 --
  27256.                 select @xpinputstr = @xpinputstr + N';' + cast(@artcol as nvarchar) 
  27257.                 if (@typestring = N'bigint')
  27258.                     select @xpinputstr = @xpinputstr + N'(19,0)'
  27259.                 else if (@typestring like N'decimal%') or (@typestring like N'numeric%')
  27260.                 begin
  27261.                     declare @startpos int
  27262.                             ,@endpos  int
  27263.  
  27264.                     select @startpos = charindex(N'(', @typestring, 1)
  27265.                     select @endpos = charindex(N')', @typestring, @startpos)
  27266.                     select @xpinputstr = @xpinputstr + substring(@typestring, @startpos, (@endpos - @startpos + 1))
  27267.                 end
  27268.                 select @cmd = N',' + quotename(@key) + N' ' + @typestring
  27269.                 insert into tempcrtcmd(procedure_text) values(@cmd)
  27270.                 select @selectcl = @selectcl + N', b.' + quotename(@key)
  27271.                 
  27272.                 if (@joincl = N'')
  27273.                 begin
  27274.                     select @joincl = @joincl + N'a.' + quotename(@key) + N' = b.' + quotename(@key)
  27275.                 end
  27276.                 else
  27277.                 begin
  27278.                     select @joincl = @joincl + N'and a.' + quotename(@key) + N' = b.' + quotename(@key)
  27279.                 end                
  27280.             end
  27281.             else
  27282.             begin
  27283.                 --
  27284.                 -- this column is not part of PK
  27285.                 -- build the select clause for this column
  27286.                 --
  27287.                 select @selectcl = @selectcl + N', a.' + quotename(@key)
  27288.             end
  27289.         end        
  27290.  
  27291.         --
  27292.         -- get the next column
  27293.         --
  27294.         FETCH #hCColid INTO @colid, @key
  27295.     end
  27296.     CLOSE #hCColid
  27297.     DEALLOCATE #hCColid
  27298.     drop table #pkcoltab
  27299.  
  27300.     --
  27301.     -- create the join table now
  27302.     --
  27303.     select @cmd = N') '
  27304.     insert into tempcrtcmd(procedure_text) values(@cmd)
  27305.     if exists (select * from dbo.sysobjects where name = N'tempqjointab')
  27306.         drop table tempqjointab
  27307.     select @cmd = 'select procedure_text from dbo.tempcrtcmd order by c1'
  27308.     exec @retcode = master..xp_execresultset @cmd, @dbname
  27309.     if (@retcode != 0)
  27310.         goto cleanup
  27311.  
  27312.     --
  27313.     -- populate the join table now
  27314.     --
  27315.     if (@update_mode in (2,3))
  27316.     begin
  27317.         --
  27318.         -- MSMQ case : one call to the xp should populate the join table
  27319.         --
  27320.         insert into tempqjointab
  27321.             exec master.dbo.xp_readpkfromqueue @tablename, @queue_id, @xpinputstr, @tranid
  27322.     end
  27323.     else
  27324.     begin
  27325.         --
  27326.         -- SQLQ case : select the data for this subscription and call the
  27327.         -- xp for each row in the cursor to populate the join table
  27328.         --
  27329.         declare @spancount int
  27330.                 ,@data varbinary(8000)
  27331.                 ,@state bit
  27332.         
  27333.         declare #hcurQInfo cursor local FAST_FORWARD FOR
  27334.         select data, cmdstate, tranid
  27335.         from dbo.MSreplication_queue
  27336.         where UPPER(publisher) = UPPER(@publisher) and
  27337.                 publisher_db = @publisher_db and
  27338.                 publication = @publication and
  27339.                 tranid = case when @tranid IS NULL then tranid else @tranid end and
  27340.                 commandtype = 1
  27341.         order by orderkey
  27342.         FOR READ ONLY
  27343.  
  27344.         select @spancount = 0
  27345.         open #hcurQInfo
  27346.         fetch #hcurQInfo into @data, @state, @tranid
  27347.         while (@@FETCH_STATUS = 0)
  27348.         begin
  27349.             declare @qbdata0 varbinary(8000)
  27350.                     ,@qbdata1 varbinary(8000)
  27351.  
  27352.             if (@state = 1)
  27353.             begin
  27354.                 --
  27355.                 -- command spanning more than a row
  27356.                 -- we will allow spanning upto 2 rows
  27357.                 --
  27358.                 if (@spancount = 0)
  27359.                     select @qbdata0 = @data
  27360.                 else
  27361.                 begin
  27362.                     raiserror('sp_getqueuedrows(debug): Queued data spans 3 rows, cannot proceed', 16, -1)
  27363.                     close #hcurQInfo
  27364.                     deallocate #hcurQInfo
  27365.                     select @retcode = 1
  27366.                     goto cleanup
  27367.                 end
  27368.                 select @spancount = @spancount + 1
  27369.             end
  27370.             else
  27371.             begin
  27372.                 --
  27373.                 -- final row for the command
  27374.                 --
  27375.                 if (@spancount = 0)
  27376.                     select @qbdata0 = @data                
  27377.                 else if (@spancount = 1)
  27378.                     select @qbdata1 = @data
  27379.                 else
  27380.                 begin
  27381.                     raiserror('sp_getqueuedrows(debug): Queued data spans 3 rows, cannot proceed', 16, -1)
  27382.                     close #hcurQInfo
  27383.                     deallocate #hcurQInfo
  27384.                     select @retcode = 1
  27385.                     goto cleanup
  27386.                 end
  27387.  
  27388.                 --
  27389.                 -- call the xp to populate the join table
  27390.                 --
  27391.                 insert into tempqjointab
  27392.                     exec master.dbo.xp_readpkfromvarbin @tablename, @xpinputstr, @tranid, @spancount, @qbdata0, @qbdata1
  27393.  
  27394.                 --
  27395.                 -- reset the span count
  27396.                 --
  27397.                 select @spancount = 0
  27398.             end
  27399.  
  27400.             --
  27401.             -- fetch the next row
  27402.             --
  27403.             fetch #hcurQInfo into @data, @state, @tranid
  27404.         end
  27405.         close #hcurQInfo
  27406.         deallocate #hcurQInfo
  27407.     end
  27408.  
  27409.     --
  27410.     -- Now perform the join
  27411.     --
  27412.     select @cmd = N'select b.action, b.tranid ' + @selectcl 
  27413.         + N'from ' + @qualified_tabname + N' a right join tempqjointab b on (' + @joincl + N') '
  27414.     exec (@cmd)
  27415.     
  27416.     --
  27417.     -- all done
  27418.     --
  27419. cleanup:    
  27420.     if exists (select * from dbo.sysobjects where name = N'tempqjointab')
  27421.         drop table tempqjointab
  27422.     if exists (select * from dbo.sysobjects where name = 'tempcrtcmd')
  27423.         drop table tempcrtcmd
  27424.     return @retcode
  27425. end
  27426. go
  27427.  
  27428. EXEC dbo.sp_MS_marksystemobject sp_getqueuedrows
  27429. GO
  27430. --
  27431. -- sp_MSprep_exclusive
  27432. --
  27433. -- Description: Helper sp for schema change, acquires shc-m lock on the source table, 
  27434. --        and 'Exclusive' application lock on all the publications it belongs to.
  27435. --
  27436. -- Note :     @objname should be owner qualified
  27437. -- Returns:
  27438. --         0 if success
  27439. --        1 if failure
  27440. --
  27441. raiserror('Creating procedure sp_MSprep_exclusive', 0,1)
  27442. go
  27443. create proc sp_MSprep_exclusive @objname sysname
  27444. as
  27445.     set nocount on
  27446.     declare @retcode int
  27447.     declare @objid int
  27448.     declare @tran_pubname sysname
  27449.  
  27450.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  27451.     IF @@ERROR <> 0 or @retcode <> 0
  27452.         return (1)
  27453.  
  27454.     if @objname is NULL
  27455.     begin
  27456.         RAISERROR (14043, 16, -1, '@objname')
  27457.         return (1)
  27458.     end
  27459.  
  27460.     select @objid = object_id(@objname)
  27461.     if @objid is NULL
  27462.     begin
  27463.         raiserror(14027, 16, -1, @objname)
  27464.         return (1)
  27465.     end
  27466.  
  27467.     exec sp_replupdateschema @objname
  27468.     if @@ERROR<>0
  27469.         return (1)
  27470.  
  27471.     declare #trancolumn CURSOR LOCAL FAST_FORWARD for 
  27472.             select p.name from sysarticles a, syspublications p where a.objid=@objid
  27473.                     and p.pubid = a.pubid
  27474.     open #trancolumn
  27475.     fetch #trancolumn into @tran_pubname
  27476.     while (@@fetch_status <> -1)
  27477.     BEGIN
  27478.         EXEC @retcode = sp_getapplock     @Resource = @tran_pubname, 
  27479.                         @LockMode = N'Exclusive', 
  27480.                         @LockOwner = N'Transaction', 
  27481.                         @LockTimeout = 0
  27482.         if @retcode = -1
  27483.         begin 
  27484.             raiserror(21386, 16, -1, @objname)
  27485.             goto FAILURE    
  27486.         end 
  27487.         if @@ERROR<>0 or @retcode < 0
  27488.             goto FAILURE
  27489.         fetch #trancolumn into @tran_pubname            
  27490.     END
  27491.     close #trancolumn
  27492.     deallocate #trancolumn
  27493.     return 0
  27494. FAILURE:
  27495.     close #trancolumn
  27496.     deallocate #trancolumn
  27497.     return (1)
  27498. go
  27499. EXEC dbo.sp_MS_marksystemobject sp_MSprep_exclusive
  27500. --
  27501. -- sp_verify_publication
  27502. --
  27503. -- Description: Invoked by user on a distributor server to perform a simple replication plumbing check.
  27504. --        Tests the connectivity of all the push subscriptions for a given publication.
  27505. --        (doesn't test pull or anonymous subscriptions)
  27506. --
  27507. -- Returns:
  27508. --         0 if success
  27509. --        1 if failure
  27510. --
  27511. raiserror('Creating procedure sp_verify_publication', 0,1)
  27512. go
  27513. create proc sp_verify_publication (
  27514.     @publisher sysname,        /*name of the publisher*/
  27515.     @publisher_db sysname,        /*the database for the publication*/
  27516.     @publication sysname,        /*name of the publication*/
  27517.     @reserved int = 0        /*reserved -- should not be used directly by user.
  27518.                       For internal use only.*/
  27519. )
  27520. AS
  27521. BEGIN
  27522. set nocount on
  27523.  
  27524. if( @reserved = 0 )
  27525. begin
  27526.   declare @proc nvarchar(255),
  27527.       @distribution_db sysname,
  27528.       @recurse_retcode int
  27529.   --
  27530.   --verify that this server is a distributor.
  27531.   --
  27532.   if (not exists( select * from msdb..sysobjects where name = 'MSdistpublishers') )
  27533.   begin
  27534.     RAISERROR(14114, 16, -1, @@SERVERNAME)
  27535.     return(1)
  27536.   end
  27537.   --
  27538.   --get the distribution database
  27539.   --
  27540.   select @distribution_db = distribution_db from msdb.dbo.MSdistpublishers where UPPER(name) = UPPER(@publisher) collate database_default
  27541.   if( @distribution_db is NULL )
  27542.   begin
  27543.     RAISERROR(21169, 16, -1, @publisher, @@SERVERNAME, @publisher)
  27544.     return(1)
  27545.   end
  27546.  
  27547.   select @proc = @distribution_db + '.dbo.sp_verify_publication'
  27548.   exec @recurse_retcode = @proc @publisher, @publisher_db, @publication, 1
  27549.   return(@recurse_retcode)
  27550. end
  27551.  
  27552. declare @publisher_id smallint,
  27553.     @subscriber sysname,
  27554.     @subscriber_db sysname,
  27555.     @type tinyint,
  27556.     @job_id binary(16),
  27557.     @publication_type int,
  27558.     @agent_type varchar(15),
  27559.     @command nvarchar(3200),
  27560.     @success varchar(300),
  27561.     @srvid smallint
  27562.  
  27563. select @srvid = srvid from master.dbo.sysservers where UPPER(srvname) = UPPER(@publisher) collate database_default
  27564. if @srvid is NULL
  27565. begin
  27566.   RAISERROR(21169, 16, -1, @publisher, @@SERVERNAME, @publisher)
  27567.   return(1)
  27568. end
  27569.  
  27570. select @publication_type = publication_type from MSpublications
  27571.   where publisher_id = @srvid and
  27572.   publisher_db = @publisher_db and
  27573.   publication = @publication
  27574.  
  27575. if @publication_type is NULL
  27576. begin
  27577.   RAISERROR(21332, 16, -1, @publication)
  27578.   return(1)
  27579. end
  27580.  
  27581. create table #T_VERIFICATION_RESULTS (
  27582.   subscriber sysname NOT NULL, subscriber_db sysname NOT NULL, type int NOT NULL,
  27583.   job_id binary(16) NULL, results varchar(300) NULL
  27584. )
  27585.  
  27586. -- Parameter Check: @publication_type
  27587. -- Make sure that the publication type is one of the following:
  27588. -- 0  transactional
  27589. -- 1  snapshot
  27590. -- 2  merge
  27591. if( @publication_type = 0 or @publication_type = 1 )
  27592.   begin
  27593.     select @agent_type = 'distribution'
  27594.  
  27595.     create table #T_SUBSCRIPTIONS (subscriber sysname NOT NULL,  status int NOT NULL, 
  27596.     subscriber_db sysname NOT NULL,
  27597.     type tinyint NOT NULL, distribution_agent nvarchar(100) NOT NULL, last_action nvarchar(255) NULL, 
  27598.     action_time nvarchar(24) NULL, start_time nvarchar(24) NULL, duration int NULL, 
  27599.     delivery_rate float NULL,
  27600.     delivery_latency int NULL, delivered_transactions int NULL, 
  27601.     delivered_commands int NULL,
  27602.     delivery_time int NULL, average_commands int NULL, 
  27603.     error_id int NULL, 
  27604.     job_id binary(16) NULL, local_job bit NULL, profile_id int NOT NULL,
  27605.     agent_id int NOT NULL, last_timestamp binary(8) NOT NULL, offload_enabled bit NOT NULL, 
  27606.     offload_server sysname NULL, subscriber_type tinyint NULL)
  27607.  
  27608.     insert #T_SUBSCRIPTIONS
  27609.       exec sp_MSenum_subscriptions @publisher, @publisher_db, @publication
  27610.  
  27611.     insert into #T_VERIFICATION_RESULTS (subscriber, subscriber_db, type, job_id)
  27612.     (select subscriber, subscriber_db, type, job_id from #T_SUBSCRIPTIONS)
  27613.  
  27614.     drop table #T_SUBSCRIPTIONS
  27615.   end
  27616. else if( @publication_type = 2 )
  27617.   begin
  27618.     select @agent_type = 'merge'
  27619.  
  27620.     create table #T_MERGE_SUBSCRIPTIONS (subscriber sysname NOT NULL,  status int NOT NULL, 
  27621.         subscriber_db sysname NOT NULL, type int NOT NULL, agent_name nvarchar(100) NOT NULL, last_action nvarchar(255) NULL, 
  27622.         action_time nvarchar(24) NULL, start_time nvarchar(24) NULL, duration int NULL, 
  27623.         delivery_rate float NULL,
  27624.         publisher_insertcount int NULL, publisher_updatecount int NULL, publisher_deletecount int NULL,
  27625.         publisher_conficts int NULL, 
  27626.         subscriber_insertcount int NULL, subscriber_updatecount int NULL, subscriber_deletecount int NULL,
  27627.         subscriber_conficts int NULL, error_id int NULL, job_id binary(16) NULL,
  27628.         local_job bit NULL, profile_id int NOT NULL, 
  27629.         agent_id int NOT NULL, last_timestamp binary(8) NOT NULL, offload_enabled bit NOT NULL, 
  27630.     offload_server sysname NULL, subscriber_type tinyint NULL)
  27631.  
  27632.     insert #T_MERGE_SUBSCRIPTIONS
  27633.       exec sp_MSenum_merge_subscriptions @publisher, @publisher_db, @publication
  27634.  
  27635.     insert into #T_VERIFICATION_RESULTS (subscriber, subscriber_db, type, job_id)
  27636.     (select subscriber, subscriber_db, type, job_id from #T_MERGE_SUBSCRIPTIONS)
  27637.  
  27638.     drop table #T_MERGE_SUBSCRIPTIONS
  27639.   end
  27640. else
  27641.   begin
  27642.     drop table #T_VERIFICATION_RESULTS
  27643.     RAISERROR(20033, 16, -1)
  27644.     return(1)
  27645.   end
  27646.  
  27647. if( not exists( select * from #T_VERIFICATION_RESULTS ) )
  27648. begin
  27649.   --
  27650.   --if #T_VERIFICATION_RESULTS is empty, then there's no subscriptions
  27651.   --
  27652.   RAISERROR(14135, 16, -1, @publisher, @publisher_db, @publication)
  27653.   drop table #T_VERIFICATION_RESULTS
  27654.   return(1)
  27655. end
  27656.  
  27657. declare subscribers_cursor cursor LOCAL FAST_FORWARD for
  27658. select subscriber, subscriber_db, type, job_id
  27659.   from #T_VERIFICATION_RESULTS
  27660.   order by subscriber, subscriber_db
  27661.  
  27662. open subscribers_cursor
  27663. fetch next from subscribers_cursor
  27664.   into @subscriber, @subscriber_db, @type, @job_id
  27665. while @@FETCH_STATUS = 0
  27666. begin
  27667.   if( @type = 0 )
  27668.   begin
  27669.     --
  27670.     --local push subscription
  27671.     --
  27672.     select @command = ''
  27673.     select @success = 'unknown'
  27674.     select @command = command from msdb.dbo.sysjobsteps
  27675.       where job_id = @job_id and
  27676.         subsystem = case @publication_type  -- 0 = Transactional 1 = Snapshot 2 = Merge
  27677.           when 0 then N'Distribution'
  27678.           when 1 then N'Distribution'
  27679.           when 2 then N'Merge'
  27680.         end
  27681.  
  27682.     exec master.dbo.xp_replproberemsrv 'local', @agent_type, @success OUTPUT, @command, 1 --(islocal)
  27683.     if( @@ERROR <> 0) return(1)
  27684.     if UPPER(@success collate SQL_Latin1_General_CP1_CS_AS) = 'FALSE'
  27685.       select 'subscriber' = @subscriber, 'subscriber database' = @subscriber_db,
  27686.          'subscription type' = case @type
  27687.             when 0 then 'push'
  27688.             when 1 then 'pull'
  27689.             when 2 then 'anonymous'
  27690.             else 'unknown'
  27691.           end
  27692.          , 'results' = 'connection failed'
  27693.     else if( ( CHARINDEX('TRUE', UPPER(@success collate SQL_Latin1_General_CP1_CS_AS)) = 1 ) and (LEN(@success) = 4) )
  27694.       select @success = 'connection succeeded'
  27695.   end
  27696.   else
  27697.   begin
  27698.     --
  27699.     --non-push subscription, not supported
  27700.     --
  27701.     select @success = 'only push subscriptions can be verified with this stored procedure'
  27702.   end
  27703.  
  27704.   update #T_VERIFICATION_RESULTS set results = @success where
  27705.     subscriber = @subscriber and
  27706.     subscriber_db = @subscriber_db and
  27707.     type = @type and
  27708.     job_id = @job_id
  27709.   --
  27710.   --get next subscription
  27711.   --
  27712.   fetch next from subscribers_cursor
  27713.     into @subscriber, @subscriber_db, @type, @job_id
  27714. end
  27715. close subscribers_cursor
  27716. deallocate subscribers_cursor
  27717.  
  27718. select subscriber, subscriber_db as 'subscriber database', 'subscription type' =
  27719.   case type
  27720.     when 0 then 'push'
  27721.     when 1 then 'pull'
  27722.     when 2 then 'anonymous'
  27723.     else 'unknown'
  27724.   end
  27725. , results from #T_VERIFICATION_RESULTS where UPPER(results collate SQL_Latin1_General_CP1_CS_AS) != 'FALSE'
  27726.  
  27727. drop table #T_VERIFICATION_RESULTS
  27728. END
  27729. go
  27730. EXEC dbo.sp_MS_marksystemobject sp_verify_publication
  27731.  
  27732. raiserror('Creating procedure sp_scriptpublicationcustomprocs',0,-1)
  27733. go
  27734. --
  27735. -- Name: sp_scriptpublicationcustomprocs
  27736. --
  27737. -- Description: This is a utility procedure for scripting out the 
  27738. --              article "custom" ins/upd/del procedures for all 
  27739. --              table articles in a publication with the auto-generate custom
  27740. --              procedure schema option enabled. This is particularly useful 
  27741. --              and in fact specifically designed for setting up no-sync 
  27742. --              subscriptions. 
  27743. -- 
  27744. -- Notes: 1) Reconciliation procedures for concurrent snapshot will
  27745. --           not be scripted by this procedure. It does not really make 
  27746. --           sense to have concurrent snapshots for no-sync subscriptions.
  27747. --        2) Custom procedures will not be scripted out for articles 
  27748. --           without the auto-generate custom procedure (0x2) schema_option.
  27749. --
  27750. -- Parameter: @publication sysname
  27751. --
  27752. -- Security: Execute permission is granted to public; procedural security 
  27753. --           check is performed inside the procedure to restrict access
  27754. --           to sysadmins and db_owners of current database. 
  27755. --
  27756. -- Example: exec Northwind.dbo.sp_scriptpublicationcustomprocs @publication = N'Northwind'
  27757. --
  27758. create procedure dbo.sp_scriptpublicationcustomprocs
  27759.     @publication sysname
  27760. as
  27761. begin
  27762.     set nocount on
  27763.  
  27764.     declare @retcode          int,
  27765.             @artid            int,
  27766.             @pubid            int,
  27767.             @cursor_allocated bit,
  27768.             @cursor_opened    bit,
  27769.             @table_created    bit,
  27770.             @ins_cmd          nvarchar(255),
  27771.             @upd_cmd          nvarchar(255),
  27772.             @del_cmd          nvarchar(255),
  27773.             @article          sysname,
  27774.             @schema_option    int,
  27775.             @repl_freq        int,
  27776.             @formattedmessage nvarchar(4000)
  27777.     
  27778.     -- Initializations 
  27779.     select @retcode = 0,
  27780.            @pubid = null,
  27781.            @cursor_allocated = 0,
  27782.            @cursor_opened = 0,
  27783.            @table_created = 0
  27784.  
  27785.     -- Security check: Sysadmins and db_owners only
  27786.     exec @retcode = sp_MSreplcheck_publish
  27787.     if @retcode <> 0 or @@error <> 0
  27788.     begin
  27789.         return 1
  27790.     end
  27791.  
  27792.     -- Make sure the current database is enabled for transaction replication
  27793.     if not exists (select * 
  27794.                      from master..sysdatabases 
  27795.                     where name = db_name() collate database_default
  27796.                       and (category & 0x1) <> 0)
  27797.     begin
  27798.         raiserror(14013, 16, -1)
  27799.         return 1
  27800.     end
  27801.  
  27802.     -- Parameter check: The specified @publication is a valid Transactional publication
  27803.  
  27804.     select @pubid = pubid, 
  27805.            @repl_freq = repl_freq
  27806.       from dbo.syspublications
  27807.      where name = @publication
  27808.     if @pubid is null
  27809.     begin
  27810.         raiserror(20026, 16, -1, @publication)
  27811.         return 1            
  27812.     end
  27813.     
  27814.     -- Don't script out custom procs for a snapshot publication
  27815.     if @repl_freq = 1
  27816.     begin
  27817.         raiserror(21515, 16, -1, @publication) 
  27818.         return 1
  27819.     end
  27820.     -- Create temp table for procedure text
  27821.     create table #proctext_scriptpublicationcustomprocs
  27822.     (
  27823.         line_no int identity(1,1) primary key,
  27824.         line nvarchar(4000)
  27825.     ) 
  27826.     if @@error<>0
  27827.     begin
  27828.         return 1
  27829.     end    
  27830.     select @table_created = 1
  27831.     
  27832.     -- Script header
  27833.     select @formattedmessage = formatmessage(21516, @publication, db_name())
  27834.     if @@error <> 0 begin select @retcode = 1 goto Failure end
  27835.     insert into #proctext_scriptpublicationcustomprocs values(N'--')
  27836.     insert into #proctext_scriptpublicationcustomprocs values(N'-- ' + @formattedmessage)
  27837.     insert into #proctext_scriptpublicationcustomprocs values(N'--')
  27838.     insert into #proctext_scriptpublicationcustomprocs values(N'')
  27839.     insert into #proctext_scriptpublicationcustomprocs values(N'')
  27840.  
  27841.     -- Open cursor through all table articles in the specified publication and script out
  27842.     -- custom procs as necessary
  27843.     
  27844.     declare harticle cursor local fast_forward for
  27845.         select artid, ins_cmd, upd_cmd, del_cmd, name, fn_replgetbinary8lodword(schema_option)
  27846.           from sysarticles
  27847.          where pubid = @pubid
  27848.            and (type & 1) <> 0
  27849.     if @@error <> 0
  27850.     begin
  27851.         select @retcode = 1
  27852.         goto Failure
  27853.     end
  27854.     select @cursor_allocated = 1
  27855.  
  27856.     open harticle
  27857.     if @@error <> 0
  27858.     begin
  27859.         select @retcode = 1
  27860.         goto Failure
  27861.     end
  27862.     select @cursor_opened = 1
  27863.     
  27864.     fetch harticle into @artid, @ins_cmd, @upd_cmd, @del_cmd, @article, @schema_option
  27865.  
  27866.     while (@@fetch_status<>-1)
  27867.     begin        
  27868.         
  27869.         if (@schema_option & 2) = 0
  27870.         begin
  27871.             
  27872.             select @formattedmessage = formatmessage(21517,@article)
  27873.             if @@error <> 0 begin select @retcode = 1 goto Failure end
  27874.             insert into #proctext_scriptpublicationcustomprocs values(N'----')
  27875.             insert into #proctext_scriptpublicationcustomprocs values(N'---- ' + @formattedmessage)
  27876.             insert into #proctext_scriptpublicationcustomprocs values(N'----')
  27877.             insert into #proctext_scriptpublicationcustomprocs values(N'')
  27878.             goto SkipArticle
  27879.         end 
  27880.  
  27881.         select @formattedmessage = formatmessage(21518,@article)
  27882.         if @@error <> 0 begin select @retcode = 1 goto Failure end
  27883.         insert into #proctext_scriptpublicationcustomprocs values(N'----')
  27884.         insert into #proctext_scriptpublicationcustomprocs values(N'---- ' + @formattedmessage)
  27885.         insert into #proctext_scriptpublicationcustomprocs values(N'----')
  27886.         insert into #proctext_scriptpublicationcustomprocs values(N'')
  27887.  
  27888.         if lower(substring(@ins_cmd,1,len(N'call'))) = N'call'
  27889.         begin
  27890.             
  27891.             insert into #proctext_scriptpublicationcustomprocs exec @retcode = sp_scriptinsproc @artid
  27892.             if @@error <> 0 or @retcode <> 0
  27893.             begin
  27894.                 select @retcode = 1
  27895.                 goto Failure
  27896.             end
  27897.             insert into #proctext_scriptpublicationcustomprocs values('go')
  27898.             insert into #proctext_scriptpublicationcustomprocs values('')
  27899.         end
  27900.         else if lower(substring(@ins_cmd,1,len(N'sql'))) = N'sql'
  27901.         begin
  27902.             select @formattedmessage = formatmessage(21519)
  27903.             if @@error <> 0 begin select @retcode = 1 goto Failure end                
  27904.             insert #proctext_scriptpublicationcustomprocs values('-- ' + @formattedmessage)
  27905.             insert #proctext_scriptpublicationcustomprocs values('')
  27906.         end
  27907.         else
  27908.         begin
  27909.             select @formattedmessage = formatmessage(21520,@ins_cmd)
  27910.             if @@error <> 0 begin select @retcode = 1 goto Failure end                
  27911.             insert #proctext_scriptpublicationcustomprocs values('-- ' + @formattedmessage)
  27912.             insert #proctext_scriptpublicationcustomprocs values('')
  27913.         end
  27914.  
  27915.         if lower(substring(@upd_cmd,1,len(N'call'))) = N'call'
  27916.         begin
  27917.             insert into #proctext_scriptpublicationcustomprocs exec @retcode = sp_scriptupdproc @artid
  27918.             if @@error <> 0 or @retcode <> 0
  27919.             begin
  27920.                 select @retcode = 1
  27921.                 goto Failure
  27922.             end
  27923.             insert into #proctext_scriptpublicationcustomprocs values('go')
  27924.             insert into #proctext_scriptpublicationcustomprocs values('')
  27925.  
  27926.         end
  27927.         else if lower(substring(@upd_cmd,1,len(N'mcall'))) = N'mcall'
  27928.         begin
  27929.             insert into #proctext_scriptpublicationcustomprocs exec @retcode = sp_scriptmappedupdproc @artid
  27930.             if @@error <> 0 or @retcode <> 0
  27931.             begin
  27932.                 select @retcode = 1
  27933.                 goto Failure
  27934.             end
  27935.             insert into #proctext_scriptpublicationcustomprocs values('go')
  27936.             insert into #proctext_scriptpublicationcustomprocs values('')
  27937.         end
  27938.         else if lower(substring(@upd_cmd,1,len(N'xcall'))) = N'xcall'
  27939.         begin
  27940.             insert into #proctext_scriptpublicationcustomprocs exec @retcode = sp_scriptxupdproc @artid
  27941.             if @@error <> 0 or @retcode <> 0
  27942.             begin
  27943.                 select @retcode = 1
  27944.                 goto Failure
  27945.             end
  27946.             insert into #proctext_scriptpublicationcustomprocs values('go')
  27947.             insert into #proctext_scriptpublicationcustomprocs values('')
  27948.         end
  27949.         else if lower(substring(@upd_cmd,1,len(N'sql'))) = N'sql'
  27950.         begin
  27951.             select @formattedmessage = formatmessage(21519)
  27952.             if @@error <> 0 begin select @retcode = 1 goto Failure end                
  27953.             insert #proctext_scriptpublicationcustomprocs values('-- ' + @formattedmessage)
  27954.             insert #proctext_scriptpublicationcustomprocs values('')
  27955.         end
  27956.         else
  27957.         begin
  27958.             select @formattedmessage = formatmessage(21520,@upd_cmd)
  27959.             if @@error <> 0 begin select @retcode = 1 goto Failure end                
  27960.             insert #proctext_scriptpublicationcustomprocs values('-- ' + @formattedmessage)
  27961.             insert #proctext_scriptpublicationcustomprocs values('')
  27962.         end
  27963.  
  27964.         if lower(substring(@del_cmd,1,len(N'call'))) = N'call'
  27965.         begin
  27966.             insert into #proctext_scriptpublicationcustomprocs exec @retcode = sp_scriptdelproc @artid
  27967.             if @@error <> 0 or @retcode <> 0
  27968.             begin
  27969.                 select @retcode = 1
  27970.                 goto Failure
  27971.             end
  27972.             insert into #proctext_scriptpublicationcustomprocs values('go')
  27973.             insert into #proctext_scriptpublicationcustomprocs values('')
  27974.         end
  27975.         else if lower(substring(@del_cmd,1,len(N'xcall'))) = N'xcall'
  27976.         begin
  27977.             insert into #proctext_scriptpublicationcustomprocs exec @retcode = sp_scriptxdelproc @artid
  27978.             if @@error <> 0 or @retcode <> 0
  27979.             begin
  27980.                 select @retcode = 1
  27981.                 goto Failure
  27982.             end
  27983.             insert into #proctext_scriptpublicationcustomprocs values('go')
  27984.             insert into #proctext_scriptpublicationcustomprocs values('')
  27985.         end
  27986.         else if lower(substring(@del_cmd,1,len(N'sql'))) = N'sql'
  27987.         begin
  27988.             select @formattedmessage = formatmessage(21519)
  27989.             if @@error <> 0 begin select @retcode = 1 goto Failure end                
  27990.             insert #proctext_scriptpublicationcustomprocs values('-- ' + @formattedmessage)
  27991.             insert #proctext_scriptpublicationcustomprocs values('')
  27992.         end
  27993.         else
  27994.         begin
  27995.             select @formattedmessage = formatmessage(21520,@del_cmd)
  27996.             if @@error <> 0 begin select @retcode = 1 goto Failure end                
  27997.             insert #proctext_scriptpublicationcustomprocs values('-- ' + @formattedmessage)
  27998.             insert #proctext_scriptpublicationcustomprocs values('')
  27999.         end
  28000. SkipArticle:
  28001.         fetch harticle into @artid, @ins_cmd, @upd_cmd, @del_cmd, @article, @schema_option
  28002.     end
  28003.     
  28004.     select '--' = line from #proctext_scriptpublicationcustomprocs order by line_no asc
  28005.    
  28006. Failure:
  28007.     if @table_created <> 0
  28008.     begin
  28009.         drop table #proctext_scriptpublicationcustomprocs
  28010.     end
  28011.     
  28012.     if @cursor_opened <> 0
  28013.     begin
  28014.         close harticle
  28015.     end
  28016.  
  28017.     if @cursor_allocated <> 0
  28018.     begin
  28019.         deallocate harticle
  28020.     end 
  28021.     return @retcode    
  28022. end
  28023. go
  28024.  
  28025. exec sp_MS_marksystemobject sp_scriptpublicationcustomprocs
  28026. ---------------------------------------------------------------------------
  28027. ---------------------------------------------------------------------------
  28028.  
  28029. grant execute on dbo.sp_scriptpublicationcustomprocs to public
  28030. grant execute on dbo.sp_enumfullsubscribers to public
  28031. grant execute on dbo.sp_addpublication to public
  28032. grant execute on dbo.sp_changepublication to public
  28033. grant execute on dbo.sp_changesubscription to public
  28034. grant execute on dbo.sp_articlecolumn to public
  28035. grant execute on dbo.sp_helparticle to public
  28036. grant execute on dbo.sp_helparticlecolumns to public
  28037. grant execute on dbo.sp_helppublication to public
  28038. grant execute on dbo.sp_publication_validation to public
  28039. grant execute on dbo.sp_marksubscriptionvalidation to public
  28040. grant execute on dbo.sp_article_validation to public
  28041. grant execute on dbo.sp_helpsubscription to public
  28042. grant execute on dbo.sp_MSscript_article_view to public
  28043. grant execute on dbo.sp_articlefilter to public
  28044. grant execute on dbo.sp_articleview to public
  28045. grant execute on dbo.sp_addarticle to public
  28046. grant execute on dbo.sp_MSgettranconflictname to public
  28047. grant execute on dbo.sp_MSmaketrancftproc to public
  28048. grant execute on dbo.sp_MSmakeconflicttable to public
  28049. grant execute on dbo.sp_scriptsubconflicttable to public
  28050. grant execute on dbo.sp_changesubstatus to public
  28051. grant execute on dbo.sp_addsubscription to public
  28052. grant execute on dbo.sp_changearticle to public
  28053. grant execute on dbo.sp_droparticle to public
  28054. grant execute on dbo.sp_droppublication to public
  28055. grant execute on dbo.sp_dropsubscription to public
  28056. grant execute on dbo.sp_subscribe to public
  28057. grant execute on dbo.sp_unsubscribe to public
  28058. grant execute on dbo.sp_refreshsubscriptions to public
  28059. grant execute on dbo.sp_reinitsubscription to public
  28060. grant exec on dbo.sp_articlesynctranprocs to public
  28061. go
  28062.  
  28063. grant exec on dbo.sp_gettypestring to public
  28064. grant exec on dbo.sp_scriptpkwhereclause to public
  28065. grant exec on dbo.sp_scriptupdateparams to public
  28066. grant exec on dbo.sp_scriptreconwhereclause to public
  28067. grant exec on dbo.sp_script_reconciliation_insproc to public
  28068. grant exec on dbo.sp_script_reconciliation_delproc to public
  28069. grant exec on dbo.sp_script_reconciliation_xdelproc to public
  28070. grant exec on dbo.sp_scriptinsproc to public
  28071. grant exec on dbo.sp_scriptdelproc to public
  28072. grant exec on dbo.sp_scriptxdelproc to public
  28073. grant exec on dbo.sp_scriptupdproc to public
  28074. grant exec on dbo.sp_scriptmappedupdproc to public
  28075. grant exec on dbo.sp_scriptdynamicupdproc to public
  28076. grant exec on dbo.sp_scriptxupdproc to public
  28077. grant exec on dbo.sp_MSscriptmvastablenci to public
  28078. grant exec on dbo.sp_MSscriptmvastablepkc to public
  28079. grant exec on dbo.sp_MSscriptmvastableidx to public
  28080. grant exec on dbo.sp_MSscriptmvastable to public
  28081. grant exec on dbo.sp_script_synctran_commands to public
  28082. grant exec on dbo.sp_MSget_synctran_commands to public
  28083. grant exec on dbo.sp_MSactivate_auto_sub to public
  28084. grant exec on dbo.sp_dropanonymousagent to public
  28085. go
  28086.  
  28087. grant execute on dbo.sp_MSscript_compensating_send to public
  28088. grant execute on dbo.sp_MSscript_insert_statement to public
  28089. grant execute on dbo.sp_MSscript_insert_subwins to public
  28090. grant execute on dbo.sp_MSscript_insert_pubwins to public
  28091. grant execute on dbo.sp_MSscript_update_statement to public
  28092. grant execute on dbo.sp_MSscript_update_subwins to public
  28093. grant execute on dbo.sp_MSscript_update_pubwins to public
  28094. grant execute on dbo.sp_MSscript_delete_statement to public
  28095. grant execute on dbo.sp_MSscript_delete_subwins to public
  28096. grant execute on dbo.sp_MSscript_compensating_insert to public
  28097. grant execute on dbo.sp_MSscript_delete_pubwins to public
  28098. grant execute on dbo.sp_MSscript_beginproc  to public
  28099. grant execute on dbo.sp_MSscript_security  to public
  28100. grant execute on dbo.sp_MSscript_endproc  to public
  28101. grant execute on dbo.sp_MSscript_sync_ins_proc  to public
  28102. grant execute on dbo.sp_MSscript_sync_upd_proc  to public
  28103. grant execute on dbo.sp_MSscript_sync_del_proc  to public
  28104. grant execute on dbo.sp_MSscript_ExecutionMode_stmt to public
  28105. grant execute on dbo.sp_MSscript_pub_upd_trig  to public
  28106. grant execute on dbo.sp_MSmark_proc_norepl to public
  28107. grant execute on dbo.sp_MSpub_adjust_identity to public
  28108. grant execute on dbo.sp_helparticledts to public
  28109. grant execute on dbo.sp_changesubscriptiondtsinfo to public
  28110. grant execute on dbo.sp_MSvalidate_subscription to public
  28111. grant exec on dbo.sp_MScomputearticlescreationorder to public
  28112. grant exec on dbo.sp_MScomputeunresolvedrefs to public
  28113. go
  28114.  
  28115. grant execute on dbo.sp_MShelptranconflictpublications to public
  28116. grant execute on dbo.sp_MShelptranconflictcounts to public
  28117. grant execute on dbo.sp_MSgettranconflictrow to public
  28118. grant execute on dbo.sp_MSgettrancftsrcrow to public
  28119. grant execute on dbo.sp_MSdeletetranconflictrow to public
  28120. grant execute on dbo.sp_MSgetarticlereinitvalue to public
  28121. grant execute on dbo.sp_MSispkupdateinconflict to public
  28122. grant execute on dbo.sp_ivindexhasnullcols to public
  28123. grant execute on dbo.fn_sqlvarbasetostr to public
  28124. grant execute on dbo.sp_replrestart to public
  28125. grant execute on dbo.sp_replsqlqgetrows to public
  28126. grant execute on dbo.sp_MSrepl_schema to public
  28127. grant execute on dbo.sp_MSpost_auto_proc to public
  28128. grant execute on dbo.sp_MSreplupdateschema to public
  28129. grant execute on dbo.sp_MSdefer_check to public
  28130. grant execute on dbo.sp_MSreenable_check to public
  28131. grant execute on dbo.sp_getqueuedrows to public
  28132. grant execute on dbo.sp_MSprep_exclusive to public
  28133. grant execute on dbo.sp_verify_publication to public
  28134. grant execute on dbo.sp_MSexternalfkreferences to public
  28135. go 
  28136.  
  28137. dump tran master with no_log
  28138. go
  28139. sp_configure 'allow updates',0
  28140. go
  28141. reconfigure with override
  28142. go
  28143.  
  28144. print ''
  28145. print 'Checking objects created by repltran.sql.'
  28146. go
  28147.  
  28148. --obsolete   exec dbo.sp_check_objects 'repl'
  28149. -- exec dbo.sp_MS_upd_sysobj_category 2  --set sysobjects.category | 2 based on crdate.
  28150. go
  28151.  
  28152.  
  28153. print ''
  28154. print 'repltran.sql completed successfully.'
  28155. go
  28156.  
  28157. dump tran master with no_log
  28158. go
  28159. checkpoint
  28160. go
  28161.