home *** CD-ROM | disk | FTP | other *** search
/ 95.86.62.111 / 95.86.62.111.tar / 95.86.62.111 / sql2000 / INSTALL / repltran.sql < prev    next >
Text File  |  2000-07-14  |  850KB  |  27,626 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_MSscriptmvastablenci' )
  600.     begin
  601.         drop procedure sp_MSscriptmvastablenci
  602.     end
  603.  
  604.     if exists ( select * from sysobjects 
  605.         where type = 'P ' and name = 'sp_MSscriptmvastablepkc' )
  606.     begin
  607.         drop procedure sp_MSscriptmvastablepkc
  608.     end
  609.  
  610.     if exists ( select * from sysobjects 
  611.         where type = 'P ' and name = 'sp_MSscriptmvastableidx' )
  612.     begin
  613.         drop procedure sp_MSscriptmvastableidx
  614.     end
  615.  
  616.     if exists ( select * from sysobjects 
  617.         where type = 'P ' and name = 'sp_MSscriptmvastable' )
  618.     begin
  619.         drop procedure sp_MSscriptmvastable
  620.     end
  621.  
  622.     if exists ( select * from sysobjects 
  623.         where type = 'P ' and name = 'sp_fetchshowcmdsinput' )
  624.     begin
  625.         drop procedure sp_fetchshowcmdsinput
  626.     end
  627.  
  628.     if exists ( select * from sysobjects 
  629.         where type = 'P ' and name = 'sp_replshowcmds' )
  630.     begin
  631.         drop procedure sp_replshowcmds
  632.     end
  633.  
  634.     if exists ( select * from sysobjects 
  635.         where type = 'P ' and name = 'sp_publication_validation' )
  636.     begin
  637.         drop procedure sp_publication_validation
  638.     end
  639.  
  640.     if exists ( select * from sysobjects 
  641.         where type = 'P ' and name = 'sp_marksubscriptionvalidation' )
  642.     begin
  643.         drop procedure sp_marksubscriptionvalidation
  644.     end
  645.  
  646.     if exists ( select * from sysobjects 
  647.         where type = 'P ' and name = 'sp_article_validation' )
  648.     begin
  649.         drop procedure sp_article_validation
  650.     end
  651.  
  652.     if exists ( select * from sysobjects 
  653.         where type = 'P ' and name = 'sp_MSdrop_6x_replication_agent' )
  654.     begin
  655.         drop procedure sp_MSdrop_6x_replication_agent
  656.     end
  657.  
  658.     if exists ( select * from sysobjects 
  659.         where type = 'P ' and name = 'sp_MSget_article_column_list' )
  660.     begin
  661.         drop procedure sp_MSget_article_column_list
  662.     end
  663.  
  664.     if exists ( select * from sysobjects 
  665.         where type = 'P ' and name = 'sp_MSpub_adjust_identity' )
  666.     begin
  667.         drop procedure sp_MSpub_adjust_identity
  668.     end
  669.  
  670.     if exists ( select * from sysobjects 
  671.         where type = 'P ' and name = 'sp_helparticledts' )
  672.     begin
  673.         drop procedure sp_helparticledts
  674.     end
  675.  
  676.     if exists ( select * from sysobjects 
  677.         where type = 'P ' and name = 'sp_changesubscriptiondtsinfo' )
  678.     begin
  679.         drop procedure sp_changesubscriptiondtsinfo
  680.     end
  681.  
  682.     if exists ( select * from sysobjects 
  683.         where type = 'P ' and name = 'sp_script_synctran_commands' )
  684.     begin
  685.         drop procedure sp_script_synctran_commands
  686.     end
  687.  
  688.     if exists ( select * from sysobjects 
  689.         where type = 'P ' and name = 'sp_MScomputearticlescreationorder' )
  690.     begin
  691.         drop procedure sp_MScomputearticlescreationorder
  692.     end
  693.  
  694.     if exists ( select * from sysobjects 
  695.         where type = 'P ' and name = 'sp_MScomputeunresolvedrefs' )
  696.     begin
  697.         drop procedure sp_MScomputeunresolvedrefs
  698.     end
  699.  
  700.     if exists ( select * from sysobjects 
  701.             where type = 'P ' and name = 'sp_MShelptranconflictpublications' )
  702.         drop procedure sp_MShelptranconflictpublications
  703.  
  704.     if exists ( select * from sysobjects 
  705.             where type = 'P ' and name = 'sp_MShelptranconflictcounts' )
  706.         drop procedure sp_MShelptranconflictcounts
  707.  
  708.     if exists ( select * from sysobjects 
  709.             where type = 'P ' and name = 'sp_MSgettranconflictrow' )
  710.         drop procedure sp_MSgettranconflictrow
  711.  
  712.     if exists ( select * from sysobjects 
  713.             where type = 'P ' and name = 'sp_MSgettrancftsrcrow' )
  714.         drop procedure sp_MSgettrancftsrcrow
  715.  
  716.     if exists ( select * from sysobjects 
  717.             where type = 'P ' and name = 'sp_MSdeletetranconflictrow' )
  718.         drop procedure sp_MSdeletetranconflictrow
  719.  
  720.     if exists ( select * from sysobjects
  721.             where type = 'P ' and name = 'sp_MSexternalfkreferences' )
  722.         drop procedure sp_MSexternalfkreferences    
  723.  
  724.     if exists ( select * from sysobjects
  725.             where type = 'P ' and name = 'sp_MSgetarticlereinitvalue' )
  726.         drop procedure sp_MSgetarticlereinitvalue    
  727.  
  728.     if exists ( select * from sysobjects
  729.             where type = 'P ' and name = 'sp_MSispkupdateinconflict' )
  730.         drop procedure sp_MSispkupdateinconflict    
  731.  
  732.     if exists ( select * from sysobjects
  733.             where type = 'P ' and name = 'sp_dropanonymousagent' )
  734.         drop procedure sp_dropanonymousagent    
  735.  
  736.     if exists ( select * from sysobjects
  737.             where type = 'P ' and name = 'sp_ivindexhasnullcols' )
  738.         drop procedure sp_ivindexhasnullcols    
  739.  
  740.     if exists (select * from sysobjects
  741.             where type = 'FN' and name = 'fn_sqlvarbasetostr')
  742.          drop function fn_sqlvarbasetostr
  743.  
  744.     if exists ( select * from sysobjects
  745.             where type = 'P ' and name = 'sp_replrestart' )
  746.         drop procedure sp_replrestart    
  747.  
  748.     if exists ( select * from sysobjects
  749.             where type = 'P ' and name = 'sp_MSreinit_article' )
  750.         drop procedure sp_MSreinit_article    
  751.  
  752.     if exists ( select * from sysobjects
  753.             where type = 'P ' and name = 'sp_replqueuemonitor' )
  754.         drop procedure sp_replqueuemonitor    
  755.  
  756.     if exists ( select * from sysobjects
  757.             where type = 'P ' and name = 'sp_replsqlqgetrows' )
  758.         drop procedure sp_replsqlqgetrows
  759.  
  760.     if exists ( select * from sysobjects
  761.             where type = 'P ' and name = 'sp_MSrepl_schema' )
  762.         drop procedure sp_MSrepl_schema    
  763.  
  764.     if exists ( select * from sysobjects
  765.             where type = 'P ' and name = 'sp_MSpost_auto_proc' )
  766.         drop procedure sp_MSpost_auto_proc    
  767.  
  768.     if exists ( select * from sysobjects
  769.             where type = 'P ' and name = 'sp_MSreplupdateschema' )
  770.         drop procedure sp_MSreplupdateschema    
  771.  
  772.     if exists ( select * from sysobjects
  773.             where type = 'P ' and name = 'sp_MSdefer_check' )
  774.         drop procedure sp_MSdefer_check    
  775.  
  776.     if exists ( select * from sysobjects
  777.             where type = 'P ' and name = 'sp_MSreenable_check' )
  778.         drop procedure sp_MSreenable_check    
  779.  
  780.     if exists ( select * from sysobjects
  781.             where type = 'P ' and name = 'sp_getqueuedrows' )
  782.         drop procedure sp_getqueuedrows    
  783.  
  784.     if exists ( select * from sysobjects
  785.             where type = 'P ' and name = 'sp_MSprep_exclusive' )
  786.         drop procedure sp_MSprep_exclusive    
  787.  
  788.     if exists ( select * from sysobjects
  789.         where type = 'P ' and name = 'sp_verify_publication' )
  790.     drop procedure sp_verify_publication
  791.  
  792.     dump tran master with no_log
  793. go
  794.  
  795. EXEC dbo.sp_MS_marksystemobject sp_MSdrop_repltran
  796. GO
  797.  
  798. EXEC dbo.sp_MSdrop_repltran
  799. GO
  800.  
  801. /* Create and execute dbo.sp_MSdrop_pub_tables */
  802.  
  803. print ''
  804. print 'Creating procedure sp_MSdrop_pub_tables'
  805. go
  806. CREATE PROCEDURE sp_MSdrop_pub_tables
  807. AS
  808.         
  809.     begin tran
  810.     save TRAN sp_drop_central_pub_tables
  811.     
  812.     /* drop 'sysarticles' */
  813.     IF exists (select * from sysobjects where name = 'sysarticles')
  814.     BEGIN
  815.         DROP TABLE sysarticles
  816.         IF @@ERROR <> 0
  817.         BEGIN
  818.             if @@trancount > 0
  819.             begin
  820.                 ROLLBACK TRAN sp_drop_central_pub_tables
  821.                 commit tran
  822.             end
  823.             RETURN(1)
  824.         END
  825.     END
  826.  
  827.     /* drop 'sysschemaarticles' */
  828.     IF exists (select * from sysobjects where name = 'sysschemaarticles')
  829.     BEGIN
  830.         DROP TABLE sysschemaarticles
  831.         IF @@ERROR <> 0
  832.         BEGIN
  833.             if @@trancount > 0
  834.             begin
  835.                 ROLLBACK TRAN sp_drop_central_pub_tables
  836.                 commit tran
  837.             end
  838.             RETURN (1)
  839.         END
  840.     END
  841.  
  842.     /* drop 'sysextendedarticlesview' */
  843.     IF exists (select * from sysobjects where name = 'sysextendedarticlesview')
  844.     BEGIN
  845.         DROP VIEW sysextendedarticlesview
  846.         IF @@ERROR <> 0
  847.         BEGIN
  848.             if @@trancount > 0
  849.             begin
  850.                 ROLLBACK TRAN sp_drop_central_pub_tables
  851.                 commit tran
  852.             end
  853.             RETURN (1)
  854.         END
  855.     END
  856.  
  857.  
  858.     /* drop 'syspublications' */
  859.     IF exists (select * from sysobjects where name = 'syspublications')
  860.     BEGIN
  861.         DROP TABLE syspublications
  862.         IF @@ERROR <> 0
  863.         BEGIN
  864.             if @@trancount > 0
  865.             begin
  866.                 ROLLBACK TRAN sp_drop_central_pub_tables
  867.                 commit tran
  868.             end
  869.             RETURN(1)
  870.         END
  871.     END
  872.  
  873.     /* drop 'syssubscriptions' */
  874.     IF exists (select * from sysobjects where name = 'syssubscriptions')
  875.     BEGIN
  876.         DROP TABLE syssubscriptions
  877.         IF @@ERROR <> 0
  878.         BEGIN
  879.             if @@trancount > 0
  880.             begin
  881.                 ROLLBACK TRAN sp_drop_central_pub_tables
  882.                 commit tran
  883.             end
  884.             RETURN(1)
  885.         END
  886.     END
  887.  
  888.     -- SyncTran
  889.     /* drop 'sysarticleupdates' */
  890.     IF exists (select * from sysobjects where name = 'sysarticleupdates')
  891.     BEGIN
  892.         DROP TABLE sysarticleupdates
  893.         IF @@ERROR <> 0
  894.         BEGIN
  895.             if @@trancount > 0
  896.             begin
  897.                 ROLLBACK TRAN sp_drop_central_pub_tables
  898.                 commit tran
  899.             end
  900.             RETURN(1)
  901.         END
  902.     END
  903.  
  904.     IF exists (select * from sysobjects where name = 'MSpub_identity_range')
  905.     BEGIN
  906.         DROP TABLE MSpub_identity_range
  907.         IF @@ERROR <> 0
  908.         BEGIN
  909.             if @@trancount > 0
  910.             begin
  911.                 ROLLBACK TRAN sp_drop_central_pub_tables
  912.                 commit tran
  913.             end
  914.             RETURN(1)
  915.         END
  916.     END
  917.     -- end SyncTran
  918.  
  919.     IF exists (select * from sysobjects where name = 'systranschemas' and uid = 1)
  920.     BEGIN
  921.         DROP TABLE dbo.systranschemas
  922.         IF @@ERROR <> 0
  923.         BEGIN
  924.             if @@trancount > 0
  925.             begin
  926.                 ROLLBACK TRAN sp_drop_central_pub_tables
  927.                 commit tran
  928.             end
  929.             RETURN(1)
  930.         END
  931.     END
  932.  
  933.     COMMIT TRAN
  934. GO
  935.  
  936. EXEC dbo.sp_MS_marksystemobject sp_MSdrop_pub_tables
  937. GO
  938.  
  939. dump tran master with no_log
  940. go
  941.  
  942. --print ''
  943. --print 'Executing procedure dbo.sp_MSdrop_pub_tables.'
  944. --go
  945. --exec dbo.sp_MSdrop_pub_tables
  946. --go
  947.  
  948. --dump tran master with no_log
  949. --go
  950.  
  951. /* Create and execute dbo.sp_MScreate_pub_tables */
  952.  
  953. dump tran master with no_log
  954. go
  955.  
  956. print ''
  957. print 'Creating procedure sp_MSarticlecolstatus'
  958. go
  959. CREATE PROCEDURE sp_MSarticlecolstatus (
  960.     @artid int,
  961.     @tabid int,
  962.     @colid int,
  963.     @type nvarchar (10),      /* 'publish', 'nonsqlsub' */
  964.     @status bit OUTPUT)
  965.     AS
  966.  
  967.     SELECT @status = 0
  968.  
  969.     IF LOWER(@type) = N'nonsqlsub'
  970.     BEGIN
  971.  
  972.         ----------------------------------------------------------
  973.         -- Check all active or subscribed articles for the column.
  974.         ----------------------------------------------------------
  975.  
  976.         IF EXISTS( SELECT sub.artid FROM sysarticles art, syssubscriptions sub, syspublications sp, master.dbo.sysservers ss
  977.                    WHERE art.objid = @tabid
  978.                    AND art.artid <> @artid
  979.                    AND sub.artid = art.artid
  980.                    AND ss.srvid = sub.srvid
  981.                    AND sp.pubid = art.pubid
  982.                    AND ( ( sub.status in(1,2) AND (ss.srvproduct = N'MSREPL-NONSQL' OR sp.allow_anonymous = 1) ) 
  983.                          OR sub.status = 3 )
  984.                    AND CONVERT(bit, CONVERT( varbinary, SUBSTRING( CONVERT( nvarchar, art.columns ), 16 - FLOOR((@colid-1)/16),1 )) & POWER(2, ((@colid-1)%16))) = 1 )
  985.         BEGIN
  986.             SELECT @status = 1
  987.         END
  988.     END
  989.     ELSE
  990.     BEGIN
  991.     
  992.         -----------------------------------------------------------
  993.         -- Check all articles for the column.
  994.         -----------------------------------------------------------
  995.  
  996.         IF EXISTS( SELECT artid FROM sysarticles 
  997.                    WHERE objid = @tabid
  998.                    AND artid <> @artid
  999.                    AND CONVERT(bit, CONVERT( varbinary, SUBSTRING( CONVERT( nvarchar, columns ), 16 - FLOOR((@colid-1)/16),1 )) & POWER(2, ((@colid-1)%16))) = 1 )
  1000.         BEGIN
  1001.             SELECT @status = 1
  1002.         END
  1003.     END
  1004.  
  1005.     RETURN (0)
  1006. GO
  1007.  
  1008. EXEC dbo.sp_MS_marksystemobject sp_MSarticlecolstatus
  1009. GO
  1010.  
  1011.  
  1012. print ''
  1013. print 'Creating procedure sp_MSarticlecol'
  1014. go
  1015. CREATE PROCEDURE sp_MSarticlecol (
  1016.     @artid int,
  1017.     @colid smallint = NULL,
  1018.     @type nvarchar(10),      /* 'publish', 'nonsqlsub' */
  1019.     @operation nvarchar(5))  /* 'add', 'drop' */
  1020.     AS
  1021.  
  1022.     /*
  1023.     ** Declarations.
  1024.     */
  1025.     DECLARE @cmd nvarchar(255)
  1026.     DECLARE @cmd1 nvarchar(255)
  1027.     DECLARE @columns binary(32)    /* Temporary storage for the converted column */
  1028.     DECLARE @tabid int        /* Article base table id */
  1029.     DECLARE @retcode int
  1030.     DECLARE @status bit
  1031.     DECLARE @publish smallint        /* Constant: 0x1000 */
  1032.     DECLARE @nonsqlsub smallint        /* Constant: 0x2000 */
  1033.     DECLARE @initiated smallint            /* Constant: 0x4000 */
  1034.     DECLARE @repldts smallint            /* Constant: 0x8000 */
  1035.     DECLARE @tinycolid tinyint, @allow_dts bit, @pubid int  /* hydra compatible colid */
  1036.  
  1037.     if @colid >= 256
  1038.     begin
  1039.     raiserror(21395, 16, -1)
  1040.         RETURN (1)
  1041.     end
  1042.  
  1043.     SELECT @tinycolid = @colid
  1044.  
  1045.     SELECT @tabid = objid, @pubid = pubid FROM sysarticles WHERE artid = @artid
  1046.  
  1047.     select @allow_dts = allow_dts from syspublications where pubid = @pubid
  1048.  
  1049.  
  1050.     SELECT @publish = 0x1000
  1051.     SELECT @nonsqlsub = 0x2000
  1052.     SELECT @initiated = 0x4000
  1053.     if @allow_dts = 1
  1054.         select @repldts = 0x8000
  1055.     else
  1056.         select @repldts = 0x0000
  1057.  
  1058.     -- loop through all columns in the article
  1059.  
  1060.     IF @colid IS NULL
  1061.     BEGIN
  1062.        DECLARE hCartcol CURSOR LOCAL FAST_FORWARD FOR
  1063.             SELECT colid FROM syscolumns, sysarticles
  1064.                 WHERE artid = @artid
  1065.                 AND id = @tabid
  1066.                 AND convert(bit, convert( varbinary, substring( convert( nvarchar, columns ), 16 - floor((colid-1)/16),1 )) & power( 2, ((colid-1)%16))) = 1
  1067.     END
  1068.     ELSE
  1069.     BEGIN
  1070.        DECLARE hCartcol CURSOR LOCAL FAST_FORWARD FOR 
  1071.             SELECT colid FROM syscolumns WHERE id = @tabid
  1072.                 AND colid = @colid
  1073.     END
  1074.  
  1075.  
  1076.     OPEN hCartcol
  1077.  
  1078.     FETCH hCartcol INTO @colid
  1079.  
  1080.     WHILE (@@fetch_status <> -1)
  1081.     BEGIN
  1082.  
  1083.        IF LOWER(@operation) = N'add'
  1084.        BEGIN
  1085.           IF LOWER(@type) = N'publish'
  1086.           BEGIN
  1087.              UPDATE syscolumns
  1088.              SET colstat = colstat | @publish
  1089.              WHERE id = @tabid
  1090.              AND colid = @colid
  1091.           END
  1092.           ELSE
  1093.           BEGIN
  1094.              UPDATE syscolumns
  1095.              SET colstat = colstat | @nonsqlsub | @repldts
  1096.              WHERE id = @tabid
  1097.              AND colid = @colid
  1098.           END
  1099.        END
  1100.        ELSE /* drop */
  1101.        BEGIN
  1102.           /*
  1103.           ** Is there another non-sql server subscription on the column?
  1104.           ** Or another article publishing the column?
  1105.           */
  1106.           EXEC @retcode = dbo.sp_MSarticlecolstatus @artid, @tabid, @colid,
  1107.           @type, @status OUTPUT
  1108.  
  1109.           IF @@error <> 0 OR @retcode <> 0
  1110.           BEGIN
  1111.              CLOSE hCartcol
  1112.             DEALLOCATE hCartcol
  1113.             RETURN (1)
  1114.           END
  1115.  
  1116.           IF (@status = 0)
  1117.           BEGIN
  1118.              IF LOWER(@type) = N'publish'
  1119.              BEGIN
  1120.                 /* Clear 'publish' bit */
  1121.                 UPDATE syscolumns
  1122.                 SET colstat = colstat & ~@publish
  1123.                 WHERE id = @tabid
  1124.                 AND colid = @colid
  1125.              END
  1126.              ELSE
  1127.              BEGIN
  1128.                 /* Clear 'non-sql server subscription' bit */
  1129.                 UPDATE syscolumns
  1130.                 SET colstat = colstat & ~@nonsqlsub & ~@repldts
  1131.                 WHERE id = @tabid
  1132.                 AND colid = @colid
  1133.              END
  1134.           END
  1135.        END
  1136.  
  1137.        FETCH hCartcol INTO @colid
  1138.  
  1139.     END
  1140.  
  1141.  
  1142.     CLOSE hCartcol
  1143.     DEALLOCATE hCartcol
  1144.  
  1145. GO
  1146.  
  1147. EXEC dbo.sp_MS_marksystemobject sp_MSarticlecol
  1148. GO
  1149.  
  1150. print ''
  1151. print 'Creating procedure sp_MScreate_pub_tables'
  1152. go
  1153. CREATE PROCEDURE sp_MScreate_pub_tables
  1154. AS
  1155.     DECLARE @fError int
  1156.     SELECT @fError = 0
  1157.  
  1158.     -- enable 'create tables as pseudo system tables
  1159.  
  1160.     -- sp_MS_upd_sysobj_category is obsolete, use sp_MS_marksystemobject instead
  1161.     -- exec dbo.sp_MS_upd_sysobj_category 1
  1162.  
  1163.  
  1164.     /* 
  1165.     ** Msg 226, Level 16, State 9
  1166.     ** CREATE TABLE system-table command not allowed within multi-statement transaction.
  1167.     */
  1168.     /*
  1169.     BEGIN TRAN sp_create_central_pub_tables
  1170.     */
  1171.     
  1172.     /* Creating 'sysarticles' */
  1173.     IF not exists (select * from sysobjects where name = 'sysarticles')
  1174.     BEGIN
  1175.         create table dbo.sysarticles
  1176.         (
  1177.         artid               int                 identity NOT NULL,
  1178.         columns             varbinary(32)       NULL,
  1179.         creation_script     nvarchar(255)       NULL,
  1180.         del_cmd             nvarchar(255)       NULL,
  1181.         description         nvarchar(255)       NULL,
  1182.         dest_table          sysname             NOT NULL,
  1183.         filter              int                 NOT NULL,
  1184.         filter_clause       ntext               NULL,
  1185.         ins_cmd             nvarchar(255)       NULL,
  1186.         name                sysname             NOT NULL,
  1187.         objid               int                 NOT NULL,
  1188.         pubid               int                 NOT NULL,
  1189.         pre_creation_cmd    tinyint             NOT NULL,
  1190.         status              tinyint             NOT NULL,
  1191.         sync_objid          int                 NOT NULL,
  1192.         type                tinyint             NOT NULL,
  1193.         upd_cmd             nvarchar(255)       NULL,
  1194.         schema_option       binary(8)           NULL,
  1195.         dest_owner          sysname             NULL
  1196.         -- Note: Please update sysextendedarticlesview whenever
  1197.         -- there is a schema change in sysarticles
  1198.         )
  1199.  
  1200.         EXEC dbo.sp_MS_marksystemobject 'sysarticles'
  1201.  
  1202.         IF @@error<>0
  1203.         BEGIN
  1204.             GOTO ERROR
  1205.         END
  1206.  
  1207.         create unique nonclustered index unc1sysarticles
  1208.             on sysarticles(artid, pubid) 
  1209.         
  1210.         IF @@error<>0
  1211.         BEGIN
  1212.             GOTO ERROR
  1213.         END
  1214.  
  1215.     END
  1216.  
  1217.     /* Creating 'sysschemaarticles' */
  1218.     IF not exists (select * from sysobjects where name = 'sysschemaarticles')
  1219.     BEGIN
  1220.         create table dbo.sysschemaarticles
  1221.         (
  1222.         artid               int                 NOT NULL,
  1223.         creation_script     nvarchar(255)       NULL,
  1224.         description         nvarchar(255)       NULL,
  1225.         dest_object         sysname             NOT NULL,
  1226.         name                sysname             NOT NULL,
  1227.         objid               int                 NOT NULL,
  1228.         pubid               int                 NOT NULL,
  1229.         pre_creation_cmd    tinyint             NOT NULL,
  1230.         status              int                 NOT NULL,
  1231.         type                tinyint             NOT NULL,
  1232.         schema_option       binary(8)           NULL,
  1233.         dest_owner          sysname             NULL
  1234.         )
  1235.         
  1236.         IF @@error<>0
  1237.         BEGIN
  1238.             GOTO ERROR
  1239.         END
  1240.  
  1241.         EXEC dbo.sp_MS_marksystemobject 'sysschemaarticles'
  1242.  
  1243.         IF @@error<>0
  1244.         BEGIN
  1245.             GOTO ERROR
  1246.         END
  1247.  
  1248.         create unique nonclustered index unc1sysschemaarticles
  1249.             on sysschemaarticles(artid, pubid)
  1250.  
  1251.         IF @@error<>0
  1252.         BEGIN
  1253.             GOTO ERROR
  1254.         END
  1255.         
  1256.     END
  1257.  
  1258.     /* Creating 'sysextendedarticlesview' */
  1259.     IF not exists (select * from sysobjects where name = 'sysextendedarticlesview')
  1260.     BEGIN
  1261.         exec ('create view dbo.sysextendedarticlesview
  1262.                as
  1263.                select * from sysarticles
  1264.                union all
  1265.                select artid, NULL, creation_script, NULL, description,
  1266.                dest_object, NULL, NULL, NULL, name, objid, pubid, 
  1267.                pre_creation_cmd, status, NULL, type, NULL, 
  1268.                schema_option, dest_owner from sysschemaarticles
  1269.                go')
  1270.  
  1271.         IF @@error<>0
  1272.         BEGIN
  1273.             GOTO ERROR
  1274.         END 
  1275.  
  1276.         EXEC dbo.sp_MS_marksystemobject 'sysextendedarticlesview'
  1277.  
  1278.         IF @@error<>0
  1279.         BEGIN
  1280.             GOTO ERROR
  1281.         END
  1282.  
  1283.     END
  1284.  
  1285.     /* Creating 'syspublications' */
  1286.     IF NOT EXISTS (select * from sysobjects where name = 'syspublications')
  1287.     BEGIN
  1288.         CREATE TABLE dbo.syspublications (
  1289.         description                 nvarchar(255)   NULL,
  1290.         name                        sysname         NOT NULL,
  1291.         pubid                       int    identity NOT NULL,
  1292.         repl_freq                   tinyint         NOT NULL,
  1293.         status                      tinyint         NOT NULL,
  1294.         sync_method                 tinyint         NOT NULL,
  1295.         snapshot_jobid              binary(16)        NULL,
  1296.         independent_agent           bit             NOT NULL,
  1297.         immediate_sync              bit             NOT NULL,
  1298.         enabled_for_internet        bit             NOT NULL,
  1299.         allow_push                  bit             NOT NULL,
  1300.         allow_pull                  bit             NOT NULL,
  1301.         allow_anonymous             bit             NOT NULL,
  1302.         immediate_sync_ready        bit             NOT NULL,
  1303.         -- SyncTran
  1304.         allow_sync_tran             bit             NOT NULL,
  1305.         autogen_sync_procs          bit             NOT NULL,
  1306.         retention                   int             NULL,
  1307.         -- The following are post 7.0
  1308.         allow_queued_tran           bit   default 0    not null, 
  1309.         -- portable snapshot support
  1310.         snapshot_in_defaultfolder           bit   default 1 NOT NULL,         
  1311.         alt_snapshot_folder         nvarchar(255)   NULL,
  1312.         -- snapshot pre/post- command
  1313.         pre_snapshot_script         nvarchar(255)   NULL,
  1314.         post_snapshot_script        nvarchar(255)   NULL,
  1315.         -- Snapshot compression
  1316.         compress_snapshot           bit   default 0 NOT NULL,          
  1317.         -- Post 7.0 Ftp support
  1318.         ftp_address                 sysname         NULL,
  1319.         ftp_port                    int   default 21 NOT NULL,
  1320.         ftp_subdirectory            nvarchar(255)   NULL,
  1321.         ftp_login                   sysname         NULL default N'anonymous',
  1322.         ftp_password                nvarchar(524)   NULL,
  1323.         allow_dts        bit default 0 not null,
  1324.         allow_subscription_copy        bit default 0 not null,
  1325.         centralized_conflicts        bit                NULL, -- 0 False, 1 True
  1326.         conflict_retention            int                NULL, -- 60
  1327.         conflict_policy                int             NULL, -- 1 = PubWins, 2 = SubWins, 3 = Reinit
  1328.         queue_type                    int                NULL,  -- 1 = MSMQ, 2 = SQL
  1329.         ad_guidname                    sysname            NULL,
  1330.         backward_comp_level    int default 10 not NULL -- default is sphinx
  1331.         )
  1332.  
  1333.         EXEC dbo.sp_MS_marksystemobject 'syspublications'
  1334.  
  1335.         IF @@ERROR <> 0
  1336.         BEGIN
  1337.             GOTO ERROR
  1338.         END
  1339.  
  1340.         create unique nonclustered index unc1syspublications
  1341.             on syspublications (pubid) 
  1342.         IF @@ERROR <> 0
  1343.         BEGIN
  1344.             GOTO ERROR
  1345.         END
  1346.  
  1347.         create unique nonclustered index unc2syspublications
  1348.             on syspublications (name)
  1349.  
  1350.         IF @@ERROR <> 0
  1351.         BEGIN
  1352.             GOTO ERROR
  1353.         END
  1354.  
  1355.     END
  1356.  
  1357.        /* Creating 'syssubscriptions' */
  1358.     IF not exists (select * from sysobjects where name = 'syssubscriptions')
  1359.     BEGIN
  1360.  
  1361.         CREATE TABLE dbo.syssubscriptions
  1362.         (
  1363.         artid                    int                NOT NULL,
  1364.         srvid                    smallint        NOT NULL,
  1365.         dest_db                    sysname        NOT NULL,
  1366.         status                    tinyint            NOT NULL,
  1367.         sync_type                tinyint            NOT NULL,
  1368.         login_name                sysname        NOT NULL,
  1369.         subscription_type        int                NOT NULL,
  1370.         distribution_jobid      binary(16)          NULL,
  1371.         timestamp NOT NULL,
  1372.         -- SyncTran
  1373.         update_mode             tinyint            NOT NULL, -- 0 (read only), 1 (Sync Tran), 
  1374.                                                              -- Queued Tran
  1375.                                                              -- 2 (Queued Tran) , 3 (Failover), 4(sqlqueued), 5(sqlqueued failover)
  1376.         loopback_detection      bit NOT NULL,
  1377.           queued_reinit           bit DEFAULT 0 NOT NULL 
  1378.       )
  1379.  
  1380.         EXEC dbo.sp_MS_marksystemobject 'syssubscriptions'
  1381.  
  1382.         IF @@ERROR <> 0
  1383.         BEGIN
  1384.             GOTO ERROR
  1385.         END
  1386.  
  1387.         create unique nonclustered index unc1syssubscriptions
  1388.             on syssubscriptions (artid, srvid, dest_db)
  1389.  
  1390.         IF @@ERROR <> 0
  1391.         BEGIN
  1392.             GOTO ERROR
  1393.         END
  1394.  
  1395.     END
  1396.  
  1397.     -- SyncTran
  1398.     /* Creating 'sysarticleupdates' */
  1399.  
  1400.     IF not exists (select * from sysobjects where name = 'sysarticleupdates')
  1401.     BEGIN
  1402.  
  1403.         CREATE TABLE dbo.sysarticleupdates
  1404.         (
  1405.         artid                  int       NOT NULL,
  1406.         pubid                  int       NOT NULL,
  1407.         sync_ins_proc          int       NOT NULL,     -- ID of sproc handling Insert Sync Transactions
  1408.         sync_upd_proc          int       NOT NULL,     -- ID of sproc handling Update Sync Transactions
  1409.         sync_del_proc          int       NOT NULL,     -- ID of sproc handling Delete Sync Transactions
  1410.         autogen                bit       NOT NULL,
  1411.         sync_upd_trig          int       NOT NULL,     -- Note 7.0 upgrade issue
  1412.         conflict_tableid       int         NULL,           -- ID of conflict table for this article
  1413.         ins_conflict_proc       int         NULL,           -- ID of sproc to log conflicts
  1414.         identity_support       bit default 0 not null  -- Whether or not do auto identity range 
  1415.         )     
  1416.  
  1417.         IF @@ERROR <> 0
  1418.         BEGIN
  1419.             GOTO ERROR
  1420.         END
  1421.  
  1422.  
  1423.         -- mark the index as a system object
  1424.         exec dbo.sp_MS_marksystemobject 'sysarticleupdates'
  1425.  
  1426.         IF @@ERROR <> 0
  1427.         BEGIN
  1428.             GOTO ERROR
  1429.         END
  1430.  
  1431.         create unique nonclustered index unc1sysarticleupdates
  1432.             on sysarticleupdates (artid, pubid)
  1433.  
  1434.         IF @@ERROR <> 0
  1435.         BEGIN
  1436.             GOTO ERROR
  1437.         END
  1438.     END
  1439.     -- end SyncTran
  1440.  
  1441.  
  1442.     IF not exists (select * from sysobjects where name = 'MSpub_identity_range')
  1443.     BEGIN
  1444.         CREATE TABLE dbo.MSpub_identity_range
  1445.         (
  1446.             objid int not null,
  1447.             range bigint not null,
  1448.             pub_range bigint not null,
  1449.             current_pub_range bigint not null,
  1450.             threshold int not null,
  1451.             last_seed bigint null -- It will be not when uninitialized.
  1452.         )     
  1453.  
  1454.         IF @@ERROR <> 0
  1455.         BEGIN
  1456.             GOTO ERROR
  1457.         END
  1458.  
  1459.  
  1460.         -- mark the index as a system object
  1461.         exec dbo.sp_MS_marksystemobject 'MSpub_identity_range'
  1462.  
  1463.         IF @@ERROR <> 0
  1464.         BEGIN
  1465.             GOTO ERROR
  1466.         END
  1467.  
  1468.         create unique nonclustered index unc1MSpub_identity_range
  1469.             on MSpub_identity_range (objid)
  1470.  
  1471.         IF @@ERROR <> 0
  1472.         BEGIN
  1473.             GOTO ERROR
  1474.         END
  1475.     END
  1476.  
  1477.     IF not exists (select * from sysobjects where name = 'systranschemas' and uid = 1)
  1478.     BEGIN
  1479.         CREATE TABLE dbo.systranschemas
  1480.         (
  1481.             tabid int not null,
  1482.             startlsn binary(10) not null,
  1483.             endlsn binary(10) not null
  1484.     )     
  1485.  
  1486.         IF @@ERROR <> 0
  1487.         BEGIN
  1488.             GOTO ERROR
  1489.         END
  1490.  
  1491.         -- mark the index as a system object
  1492.         exec dbo.sp_MS_marksystemobject 'systranschemas'
  1493.  
  1494.         IF @@ERROR <> 0
  1495.         BEGIN
  1496.             GOTO ERROR
  1497.         END
  1498.  
  1499.         create unique clustered index uncsystranschemas
  1500.             on systranschemas (startlsn)
  1501.  
  1502.         IF @@ERROR <> 0
  1503.         BEGIN
  1504.             GOTO ERROR
  1505.         END
  1506.     END
  1507.  
  1508. CLEANUP:
  1509.  
  1510.     -- disable 'create tables as pseudo system tables
  1511.     -- sp_MS_upd_sysobj_category is obsolete, use sp_MS_marksystemobject instead
  1512.     -- exec dbo.sp_MS_upd_sysobj_category 2
  1513.     RETURN( @fError )
  1514.  
  1515. ERROR:
  1516.  
  1517.     select @fError = 1
  1518.     GOTO CLEANUP
  1519.  
  1520. GO
  1521.  
  1522. EXEC dbo.sp_MS_marksystemobject sp_MScreate_pub_tables
  1523. GO
  1524.  
  1525. dump tran master with no_log
  1526. go
  1527.  
  1528. /*
  1529. ** Create replication stored procedures.
  1530. ** Part 2:  create all other stored procedures.
  1531. */
  1532.  
  1533. create proc sp_MSsetfilterparent @filter_name nvarchar(386), @parent_id int
  1534. as
  1535.    -- SQL SERVER 7.0 ONLY update sysobjects, set parent id = underlying
  1536.    -- object id
  1537.  
  1538.     declare @retcode int
  1539.     exec @retcode = dbo.sp_MSreplcheck_publish
  1540.     if @@ERROR <> 0 or @retcode <> 0
  1541.         return(1)
  1542.  
  1543.     -- Don't bother to do anything if filter name is null or empty
  1544.     if @filter_name is null or @filter_name = N''
  1545.         return 0
  1546.  
  1547.  
  1548.    BEGIN TRAN
  1549.  
  1550.    exec dbo.sp_replupdateschema @filter_name 
  1551.    update sysobjects set parent_obj = @parent_id where id = object_id( @filter_name )
  1552.    exec dbo.sp_replupdateschema @filter_name 
  1553.  
  1554.    COMMIT TRAN
  1555.  
  1556. go
  1557.  
  1558.  
  1559. EXEC dbo.sp_MS_marksystemobject sp_MSsetfilterparent
  1560. GO
  1561.  
  1562. create proc sp_MSdoesfilterhaveparent @filter_id int
  1563. as
  1564.     declare @retcode int
  1565.     exec @retcode = dbo.sp_MSreplcheck_publish
  1566.     if @@ERROR <> 0 or @retcode <> 0
  1567.         return(1)
  1568.  
  1569.     if exists ( select * from sysobjects
  1570.                 where id = @filter_id and
  1571.                 parent_obj <> 0 )
  1572.     BEGIN
  1573.         return 1
  1574.     END
  1575.     ELSE
  1576.     BEGIN
  1577.         return 0
  1578.     END
  1579. go
  1580.  
  1581. EXEC dbo.sp_MS_marksystemobject sp_MSdoesfilterhaveparent
  1582. GO
  1583.  
  1584.  
  1585. create proc sp_MSsetfilteredstatus @object_id int
  1586. as
  1587.     declare @qualified_name nvarchar(512)
  1588.  
  1589.     declare @retcode int
  1590.     exec @retcode = dbo.sp_MSreplcheck_publish
  1591.     if @@ERROR <> 0 or @retcode <> 0
  1592.         return(1)
  1593.  
  1594.     exec dbo.sp_MSget_qualified_name @object_id, @qualified_name output
  1595.  
  1596.    BEGIN TRANSACTION
  1597.    
  1598.    exec dbo.sp_replupdateschema @qualified_name
  1599.         
  1600.    if exists( select * from sysobjects where type = 'RF' and parent_obj = @object_id )
  1601.       or exists( select * from sysarticles where objid = @object_id and ( upd_cmd like 'CALL%' OR upd_cmd like 'XCALL%' ) 
  1602.       or exists( select * from sysarticles sa, syssubscriptions ss where sa.artid = ss.artid and ss.status = 3) )
  1603.    begin
  1604.        update sysobjects set replinfo = replinfo | 32 where id = @object_id
  1605.    end
  1606.    else
  1607.    begin
  1608.        update sysobjects set replinfo = replinfo & ~32 where id = @object_id
  1609.    end
  1610.  
  1611.    exec dbo.sp_replupdateschema @qualified_name
  1612.  
  1613.    COMMIT TRANSACTION
  1614.    
  1615. go
  1616.  
  1617. EXEC dbo.sp_MS_marksystemobject sp_MSsetfilteredstatus
  1618. GO
  1619.  
  1620. CREATE PROCEDURE sp_MSretrieve_publication 
  1621. @publication sysname
  1622. AS
  1623. declare @retcode int
  1624. /*
  1625. ** Security Check
  1626. */
  1627. exec @retcode = dbo.sp_MSreplcheck_publish
  1628. if @@ERROR <> 0 or @retcode <> 0
  1629.     return(1)
  1630.  
  1631. select 'Name' = name, 
  1632.         'database ' = db_name(), 
  1633.         'publisher' = @@SERVERNAME, 
  1634.         'type' = case when LOWER(repl_freq)=1 then 'Snapshot' else 'Transactional' end, 
  1635.         'description ' = description, 
  1636.         'status ' = status,  
  1637.         'allow known pull subscription' = allow_pull, 
  1638.         'allow immediate-updating subscription ' = allow_sync_tran,
  1639.         'allow anonymous ' = allow_anonymous,  
  1640.         'allow queued-updating subscription ' = allow_queued_tran, 
  1641.         'allow snapshot files FTP downloading' = enabled_for_internet, 
  1642.         'third party' = sync_method 
  1643.     from syspublications
  1644.     where name = @publication
  1645. go
  1646.  
  1647. EXEC dbo.sp_MS_marksystemobject sp_MSretrieve_publication
  1648. GO
  1649.  
  1650.  
  1651.  
  1652. CREATE PROCEDURE sp_MSreplsup_table_has_pk @tabid INT
  1653. as
  1654.  
  1655. -- if it's a table, check that it has a PK
  1656. -- if it's a view, see if it has an index ( MVs must have a unique CI )
  1657.  
  1658.     IF EXISTS (SELECT so1.* FROM sysobjects so1, sysobjects so2
  1659.                    WHERE so1.parent_obj = @tabid
  1660.                    AND so1.xtype = 'PK'
  1661.                    AND so2.id = so1.parent_obj
  1662.                    AND so2.xtype = 'U')
  1663.     BEGIN
  1664.         RETURN 1
  1665.     END
  1666.  
  1667.     IF EXISTS (SELECT * from sysobjects so, sysindexes si
  1668.                     WHERE so.id = @tabid
  1669.                     AND so.xtype = 'V'
  1670.                     AND si.id = so.id )
  1671.     BEGIN
  1672.         -- evaluate keys, make sure none are nullable
  1673.         DECLARE @indkey int
  1674.         DECLARE @objname nvarchar(256)
  1675.  
  1676.         SELECT @indkey = 1
  1677.         select @objname = QUOTENAME(user_name(OBJECTPROPERTY(@tabid, 'OwnerId'))) collate database_default + N'.' + QUOTENAME(object_name( @tabid )) collate database_default 
  1678.  
  1679.         WHILE @indkey <= 16 and index_col( @objname, 1, @indkey ) is not null
  1680.         BEGIN
  1681.             IF NOT EXISTS( SELECT * FROM syscolumns 
  1682.                         WHERE id = @tabid
  1683.                         AND name = index_col( @objname, 1, @indkey )
  1684.                         AND isnullable = 0 )
  1685.             BEGIN
  1686.                 RETURN 0
  1687.             END
  1688.  
  1689.             SELECT @indkey = @indkey + 1
  1690.         END
  1691.         RETURN 1
  1692.     END
  1693.     ELSE
  1694.     BEGIN
  1695.         RETURN 0
  1696.     END
  1697. go
  1698.  
  1699. EXEC dbo.sp_MS_marksystemobject sp_MSreplsup_table_has_pk
  1700. GO
  1701.  
  1702. CREATE PROCEDURE sp_replsync (
  1703.     @publisher sysname,    
  1704.     @publisher_db sysname,        
  1705.     @publication sysname,    
  1706.     @article sysname = '%' 
  1707.     ) AS
  1708.  
  1709.     SET NOCOUNT ON
  1710.     RAISERROR (21023, 16, -1,'sp_replsync')
  1711.     RETURN(1)
  1712. GO
  1713.  
  1714. EXEC dbo.sp_MS_marksystemobject sp_replsync
  1715. GO
  1716.  
  1717.  
  1718. print ''
  1719. print 'Creating procedure sp_enumfullsubscriber'
  1720. go
  1721.  
  1722. CREATE PROCEDURE sp_enumfullsubscribers (
  1723.         @publication sysname = '%'      /* The publication name */
  1724.     ) AS
  1725.  
  1726.     /*
  1727.     ** Declarations.
  1728.     */
  1729.  
  1730.     DECLARE @retcode int
  1731.  
  1732.     /*
  1733.     ** Security Check
  1734.     */
  1735.     exec @retcode = dbo.sp_MSreplcheck_publish
  1736.     if @@ERROR <> 0 or @retcode <> 0
  1737.         return(1)
  1738.  
  1739.     /*
  1740.     ** Parameter Check: @publication.
  1741.     ** Check to make sure that the publication exists and that it conforms
  1742.     ** to the rules for identifiers.
  1743.     */
  1744.  
  1745.     IF @publication IS NOT NULL
  1746.         BEGIN
  1747.  
  1748.             IF @publication <> '%'
  1749.                 BEGIN
  1750.                     EXECUTE @retcode = dbo.sp_validname @publication
  1751.  
  1752.                     IF @retcode <> 0
  1753.                     RETURN (1)
  1754.                 END
  1755.  
  1756.             IF NOT EXISTS (SELECT * FROM syspublications WHERE name LIKE @publication)
  1757.                 BEGIN
  1758.                     RAISERROR (20026, 11, -1, @publication)
  1759.                     RETURN (1)
  1760.                 END
  1761.  
  1762.         END
  1763.  
  1764.     ELSE
  1765.         BEGIN
  1766.             RAISERROR (14043, 16, -1, '@publication')
  1767.             RETURN (1)
  1768.         END
  1769.  
  1770.     /*
  1771.     ** Select all subscribers who subscribe to all articles in the desired
  1772.     ** publication.
  1773.     */
  1774.  
  1775.     SELECT DISTINCT 'subscriber' = sv.srvname
  1776.       FROM syspublications p,
  1777.            sysextendedarticlesview s,
  1778.            syssubscriptions ss,
  1779.            master..sysservers sv
  1780.      WHERE p.name LIKE @publication collate database_default
  1781.        AND p.pubid = s.pubid
  1782.        AND s.artid = ss.artid
  1783.        AND ss.srvid = sv.srvid
  1784.        AND NOT EXISTS (SELECT *
  1785.                          FROM sysextendedarticlesview s2
  1786.                         WHERE s2.pubid = p.pubid
  1787.                           AND NOT EXISTS (SELECT *
  1788.                                             FROM syssubscriptions ss2,
  1789.                                                  master..sysservers sv2
  1790.                                            WHERE s2.artid = ss2.artid
  1791.                                              AND ss2.srvid = sv2.srvid
  1792.                                              AND sv2.srvid = sv.srvid))
  1793. go
  1794.  
  1795.  
  1796. EXEC dbo.sp_MS_marksystemobject sp_enumfullsubscribers
  1797. GO
  1798.  
  1799. print ''
  1800. print 'Creating procedure sp_addpublication.'
  1801. go
  1802.  
  1803.  
  1804. CREATE PROCEDURE sp_addpublication (
  1805.     @publication            sysname,                          /* publication name */
  1806.     @taskid                    int = 0,                          /* backward compatible */
  1807.     @restricted                nvarchar (10) = 'false',          /* publication security */
  1808.     @sync_method            nvarchar(13) = 'native',          /* (bcp) native, (bcp) character */
  1809.     @repl_freq                nvarchar(10) = 'continuous',      /* continuous, snapshot */
  1810.     @description            nvarchar (255) = NULL,            /* publication description */
  1811.     @status                    nvarchar(8) = 'inactive',         /* publication status; 0=inactive, 1=active */
  1812.     @independent_agent        nvarchar(5) = 'false',            /* true or false */
  1813.     @immediate_sync            nvarchar(5) = 'false',            /* true or false */
  1814.     @enabled_for_internet    nvarchar(5) = 'false',            /* true or false */
  1815.     @allow_push                nvarchar(5) = 'true',             /* true or false */
  1816.     @allow_pull                nvarchar(5) = 'false',            /* true or false */
  1817.     @allow_anonymous        nvarchar(5) = 'false',            /* true or false */
  1818.     -- SyncTran
  1819.     @allow_sync_tran        nvarchar(5) = 'false',            /* true or false */
  1820.     @autogen_sync_procs        nvarchar(5) = 'true',             /* auto gen sync tran procs per article */
  1821.     @retention                int = 336,                        /* 14  days */
  1822.     @allow_queued_tran      nvarchar(5) = 'false',
  1823.     -- Portable Snapshot
  1824.     @snapshot_in_defaultfolder      nvarchar(5) = 'true',
  1825.     @alt_snapshot_folder    nvarchar(255) = NULL,
  1826.     -- Snapshot pre/post- commands
  1827.     @pre_snapshot_script    nvarchar(255) = NULL,
  1828.     @post_snapshot_script   nvarchar(255) = NULL,
  1829.     -- Snapshot compression
  1830.     @compress_snapshot      nvarchar(5) = 'false',
  1831.     -- Post 7.0 FTP
  1832.     @ftp_address            sysname = NULL,
  1833.     @ftp_port                   int = 21,
  1834.     @ftp_subdirectory       nvarchar(255) = NULL,
  1835.     @ftp_login              sysname = N'anonymous',
  1836.     @ftp_password           sysname = NULL,
  1837.     @allow_dts                nvarchar(5)    = 'false',
  1838.     @allow_subscription_copy nvarchar(5) = 'false',
  1839.     @conflict_policy        nvarchar(100) = NULL,     -- NULL, 'pub wins', 'sub reinit', 'sub wins'
  1840.     @centralized_conflicts    nvarchar(5) = NULL,     -- NULL, 'true', 'false'
  1841.     @conflict_retention        int = 14,
  1842.     @queue_type                nvarchar(10) = NULL,    -- NULL, 'msmq', 'sql'
  1843.     @add_to_active_directory    nvarchar(10) = 'false',
  1844.     @logreader_job_name sysname = NULL,
  1845.     @qreader_job_name sysname = NULL
  1846.     ) 
  1847. AS
  1848. BEGIN
  1849.  
  1850.     SET NOCOUNT ON
  1851.  
  1852.     /*
  1853.     ** Declarations.
  1854.     */
  1855.  
  1856.     DECLARE @retcode    int         /* return code value for procedure execution */
  1857.     DECLARE @rfid tinyint           /* identifier for replication frequency */
  1858.     DECLARE @publish_bit smallint   /* publication bit (flag) in sysobjects */
  1859.     DECLARE @smid tinyint           /* identifier for sync method */
  1860.     DECLARE @statid tinyint         /* status id based on @status */
  1861.     DECLARE @subs_type_id tinyint   /* subscription type id based on @subscription_type */
  1862.     DECLARE @distributor sysname
  1863.     DECLARE @distribdb sysname
  1864.     DECLARE @distproc nvarchar (255)
  1865.     DECLARE @agentname nvarchar (40)
  1866.     DECLARE @dbname sysname
  1867.     DECLARE @mergepublish_bit smallint
  1868.     DECLARE @found int
  1869.     DECLARE @independent_agent_id bit
  1870.     DECLARE @immediate_sync_id bit
  1871.     DECLARE @enabled_for_internet_id bit
  1872.     DECLARE @allow_push_id bit
  1873.     DECLARE @allow_pull_id bit
  1874.     DECLARE @allow_anonymous_id bit
  1875.     DECLARE @pubid int
  1876.     declare @distgroup sysname
  1877.     DECLARE @enc_ftp_password nvarchar(524)
  1878.     DECLARE @ad_guidname    sysname
  1879.     
  1880.     -- SyncTran
  1881.     DECLARE @allow_sync_tran_id bit
  1882.     DECLARE @allow_queued_tran_id bit
  1883.     DECLARE @autogen_sync_procs_id bit
  1884.     DECLARE @conflict_policy_id int
  1885.     DECLARE @centralized_conflicts_bit bit
  1886.             , @queue_type_val int
  1887.     
  1888.     -- Portable snapshot
  1889.     DECLARE @snapshot_in_defaultfolder_bit int 
  1890.  
  1891.     -- Snapshot compression
  1892.     DECLARE @compress_snapshot_bit bit
  1893.  
  1894.     declare @qv_replication varchar(10)
  1895.     declare @qv_replication_unlimited integer
  1896.     declare @qv_value_replication integer
  1897.  
  1898.     declare @backward_comp_level int
  1899.     select @backward_comp_level = 10 -- default to sphinx
  1900.     select @allow_sync_tran_id = 0
  1901.             ,@autogen_sync_procs_id = 0
  1902.             ,@allow_queued_tran_id = 0
  1903.             ,@qv_replication = '2745196162'
  1904.             ,@qv_replication_unlimited = 0
  1905.     
  1906.     /*
  1907.     ** The default value for TRAN publication is always 72 hours
  1908.     */
  1909.     if @retention is NULL
  1910.     BEGIN
  1911.         RAISERROR(20081, 16, -1, 'retention')
  1912.         RETURN (1)
  1913.     END
  1914.     
  1915.     /*
  1916.     **  A @retention value of zero means an infinite retention period
  1917.     */
  1918.     if @retention < 0
  1919.     BEGIN
  1920.         RAISERROR (20050, 16, -1, 1)
  1921.         RETURN(1)
  1922.     END
  1923.  
  1924.     SELECT @publish_bit         = 32
  1925.     SELECT @mergepublish_bit    = 4
  1926.  
  1927.     /*
  1928.     ** Security Check
  1929.     */
  1930.  
  1931.     exec @retcode = dbo.sp_MSreplcheck_publish
  1932.     if @@ERROR <> 0 or @retcode <> 0
  1933.         return(1)
  1934.  
  1935.     /*
  1936.     ** Check to see if the database has been activated for publication.
  1937.     */
  1938.  
  1939.     IF (SELECT category & 1
  1940.           FROM master..sysdatabases
  1941.          WHERE name = DB_NAME() collate database_default) = 0
  1942.  
  1943.     BEGIN
  1944.         RAISERROR (14013, 16, -1)
  1945.         RETURN (1)
  1946.     END
  1947.  
  1948.     IF @taskid <> 0
  1949.     BEGIN
  1950.         -- No longer supported
  1951.         RAISERROR (21023, 16, -1,'@taskid')
  1952.         RETURN(1)
  1953.     END
  1954.  
  1955.     /*
  1956.     ** Parameter Check: @publication.
  1957.     ** The @publication name must conform to the rules for identifiers,
  1958.     ** and must not be the keyword 'all'.
  1959.     */
  1960.  
  1961.     IF @publication IS NULL
  1962.         BEGIN
  1963.             RAISERROR (14043, 16, -1, '@publication')
  1964.             RETURN (1)
  1965.         END
  1966.  
  1967.     exec @retcode = dbo.sp_MSreplcheck_name @publication
  1968.     if @@ERROR <> 0 or @retcode <> 0
  1969.         return(1)
  1970.  
  1971.     IF LOWER (@publication) = 'all'
  1972.         BEGIN
  1973.             RAISERROR (14034, 16, -1)
  1974.             RETURN (1)
  1975.         END
  1976.  
  1977.     /*
  1978.     **  Check if the publication already exists.
  1979.     **  1. Check transaction-level publications
  1980.     **  2. Check merge publications
  1981.     */
  1982.  
  1983.     IF EXISTS (SELECT * FROM syspublications WHERE name = @publication)
  1984.         BEGIN
  1985.             RAISERROR (14016, 16, -1, @publication)
  1986.             RETURN (1)
  1987.         END
  1988.     
  1989.     if (select category & @mergepublish_bit from master..sysdatabases where name = DB_NAME() collate database_default) <> 0
  1990.         begin
  1991.             EXEC @retcode = dbo.sp_helpmergepublication @publication, @found output
  1992.  
  1993.             IF @@ERROR <> 0 OR @retcode <> 0
  1994.             BEGIN
  1995.                 RETURN (1)
  1996.             END
  1997.  
  1998.             IF @found <> 0 
  1999.             BEGIN
  2000.                 RAISERROR (20025, 16, -1, @publication)
  2001.                 RETURN (1)
  2002.             END
  2003.         end
  2004.  
  2005.     /*
  2006.     ** Get distribution server information for remote RPC
  2007.     ** agent verification.
  2008.     */
  2009.     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  2010.                  @distribdb = @distribdb OUTPUT
  2011.  
  2012.     IF @@error <> 0 OR @retcode <> 0
  2013.         BEGIN
  2014.         RAISERROR (14071, 16, -1)
  2015.             RETURN (1)
  2016.     END
  2017.  
  2018.  
  2019.     /*
  2020.     ** Parameter Check: @sync_method
  2021.     ** The synchronization method must be one of the following:
  2022.     **
  2023.     **      0  [bcp] native
  2024.     **      1  [bcp] character
  2025.     **        2  dump database
  2026.     **        3  concurrent
  2027.     **        4  concurrent character
  2028.     */
  2029.  
  2030.     SELECT @sync_method = LOWER(@sync_method)                                        
  2031.  
  2032.     IF @sync_method IS NULL OR @sync_method NOT IN ('native', 'character', 'bcp native', 'bcp character', 'dump database', 'concurrent', 'concurrent_c')
  2033.         BEGIN
  2034.             RAISERROR (14014, 16, -1)
  2035.             RETURN (1)
  2036.         END
  2037.  
  2038.     IF @sync_method = 'concurrent_c'
  2039.         SELECT @smid = 4
  2040.     ELSE IF @sync_method = 'concurrent'
  2041.         SELECT @smid = 3
  2042.     ELSE IF @sync_method = 'dump database'
  2043.     begin
  2044.         SELECT @smid = 2                   
  2045.         select @backward_comp_level = 40 -- not sure if we are using this, but has to be shiloh feature
  2046.     end
  2047.     ELSE IF @sync_method IN ('character', 'bcp character')
  2048.         SELECT @smid = 1
  2049.     ELSE 
  2050.         SELECT @smid = 0
  2051.  
  2052.     /*
  2053.     ** Parameter Check: @repl_freq.
  2054.     ** Make sure that the replication frequency is one of the following:
  2055.     **
  2056.     **  id  frequency
  2057.     **  ==  ==========
  2058.     **   0  continuous
  2059.     **   1  snapshot
  2060.     */
  2061.  
  2062.     SELECT @repl_freq = LOWER(@repl_freq)
  2063.     IF @repl_freq IS NULL OR @repl_freq NOT IN ('continuous', 'snapshot')
  2064.         BEGIN
  2065.             RAISERROR (14015, 16, -1)
  2066.             RETURN (1)
  2067.         END
  2068.  
  2069.     IF @repl_freq = 'snapshot' SELECT @rfid = 1
  2070.     ELSE SELECT @rfid = 0
  2071.  
  2072.     -- disable tran publishing on REPLICATION_LIMITED sku
  2073.     exec @qv_value_replication = master.dbo.sp_MSinstance_qv @qv_replication     
  2074.     if (@rfid = 0) and ( @qv_value_replication != @qv_replication_unlimited ) 
  2075.     begin
  2076.         raiserror(21108, 16, -1)
  2077.         return (1)
  2078.     end
  2079.  
  2080.     /*
  2081.     ** Parameter Check:  @restricted.
  2082.     */
  2083.  
  2084.     IF (@restricted IS NULL) OR (LOWER(@restricted) NOT IN ('true', 'false'))
  2085.         BEGIN
  2086.             RAISERROR (14017, 16, -1)
  2087.             RETURN (1)
  2088.         END
  2089.  
  2090.     /*
  2091.     ** Restricted publications are no longer supported
  2092.     */
  2093.     IF LOWER(@restricted) = 'true'
  2094.     BEGIN
  2095.         RAISERROR (14147, 16, -1)
  2096.         RETURN(1)
  2097.     END
  2098.  
  2099.     /*
  2100.     ** Parameter Check:  @status.
  2101.     ** The @status value can be:
  2102.     **
  2103.     **      statid  status
  2104.     **      ======  ========
  2105.     **           0  inactive
  2106.     **           1  active
  2107.     */
  2108.  
  2109.     IF @status IS NULL OR LOWER(@status) NOT IN ('inactive', 'active')
  2110.         BEGIN
  2111.             RAISERROR (14012, 16, -1)
  2112.             RETURN (1)
  2113.         END
  2114.  
  2115.     IF LOWER(@status) = 'active' 
  2116.     begin
  2117.         SELECT @statid = 1
  2118.     end
  2119.     ELSE 
  2120.     begin
  2121.         SELECT @statid = 0
  2122.     end
  2123.  
  2124.     /*
  2125.     ** Parameter Check:  @independent_agent.
  2126.     */
  2127.  
  2128.     IF @independent_agent IS NULL OR LOWER(@independent_agent) NOT IN ('true', 'false')
  2129.         BEGIN
  2130.             RAISERROR (14148, 16, -1, '@independent_agent')
  2131.             RETURN (1)
  2132.         END
  2133.  
  2134.     IF LOWER(@independent_agent) = 'true' SELECT @independent_agent_id = 1
  2135.     ELSE SELECT @independent_agent_id = 0
  2136.  
  2137.     /*
  2138.     ** Parameter Check:  @immediate_sync.
  2139.     */
  2140.  
  2141.     IF @immediate_sync IS NULL OR LOWER(@immediate_sync) NOT IN ('true', 'false')
  2142.         BEGIN
  2143.             RAISERROR (14148, 16, -1, '@immediate_sync')
  2144.             RETURN (1)
  2145.         END
  2146.  
  2147.     IF LOWER(@immediate_sync) = 'true' SELECT @immediate_sync_id = 1
  2148.     ELSE SELECT @immediate_sync_id = 0
  2149.  
  2150.     /*
  2151.     ** Parameter Check:  @enabled_for_internet.
  2152.     */
  2153.  
  2154.     IF @enabled_for_internet IS NULL OR LOWER(@enabled_for_internet) NOT IN ('true', 'false')
  2155.         BEGIN
  2156.             RAISERROR (14148, 16, -1, '@enabled_for_internet')
  2157.             RETURN (1)
  2158.         END
  2159.  
  2160.     IF LOWER(@enabled_for_internet) = 'true' SELECT @enabled_for_internet_id = 1
  2161.     ELSE SELECT @enabled_for_internet_id = 0
  2162.  
  2163.     IF @enabled_for_internet_id = 1 AND (@alt_snapshot_folder IS NULL OR
  2164.         @alt_snapshot_folder = N'')
  2165.         BEGIN
  2166.             RAISERROR (21159, 16, -1)
  2167.             RETURN (1) 
  2168.         END
  2169.  
  2170.     /*
  2171.     ** Parameter Check:  @allow_push.
  2172.     */
  2173.  
  2174.     IF @allow_push IS NULL OR LOWER(@allow_push) NOT IN ('true', 'false')
  2175.         BEGIN
  2176.             RAISERROR (14148, 16, -1, '@allow_push')
  2177.             RETURN (1)
  2178.         END
  2179.     IF LOWER(@allow_push) = 'true' SELECT @allow_push_id = 1
  2180.     ELSE SELECT @allow_push_id = 0
  2181.  
  2182.     /*
  2183.     ** Parameter Check:  @allow_pull.
  2184.     */
  2185.  
  2186.     IF @allow_pull IS NULL OR LOWER(@allow_pull) NOT IN ('true', 'false')
  2187.         BEGIN
  2188.             RAISERROR (14148, 16, -1, '@allow_pull')
  2189.             RETURN (1)
  2190.         END
  2191.     IF LOWER(@allow_pull) = 'true' SELECT @allow_pull_id = 1
  2192.     ELSE SELECT @allow_pull_id = 0
  2193.  
  2194.     /*
  2195.     ** Parameter Check:  @allow_anonymous.
  2196.     */
  2197.  
  2198.     IF @allow_anonymous IS NULL OR LOWER(@allow_anonymous) NOT IN ('true', 'false')
  2199.         BEGIN
  2200.             RAISERROR (14148, 16, -1, '@allow_anonymous')
  2201.             RETURN (1)
  2202.         END
  2203.     IF LOWER(@allow_anonymous) = 'true' SELECT @allow_anonymous_id = 1
  2204.     ELSE SELECT @allow_anonymous_id = 0
  2205.  
  2206.     /* Immediate_sync publications have to be independent_agent */
  2207.     IF @immediate_sync_id = 1 AND @independent_agent_id = 0
  2208.     BEGIN
  2209.             RAISERROR (21022, 16, -1)
  2210.             RETURN (1)
  2211.     END
  2212.  
  2213.     /*
  2214.     ** Parameter Check:  @add_to_active_directory.
  2215.     */
  2216.  
  2217.     if LOWER(@add_to_active_directory) NOT IN ('true', 'false')
  2218.         BEGIN
  2219.             RAISERROR (14148, 16, -1, '@add_to_active_directory')
  2220.             RETURN (1)
  2221.         END
  2222.  
  2223.    /* Is AD supported? */
  2224.    DECLARE @retval  INT
  2225.    EXECUTE @retval = master.dbo.xp_MSADEnabled
  2226.    if (@retval <> 0) and LOWER(@add_to_active_directory)='true'
  2227.    begin
  2228.         RAISERROR(21253, 16, -1)
  2229.         RETURN (1)
  2230.    end
  2231.  
  2232.     /* 
  2233.     ** Non-immediate sync do not support anonymous subscriptions.
  2234.     */
  2235.     IF @immediate_sync_id = 0 AND @allow_anonymous_id = 1
  2236.     BEGIN
  2237.             RAISERROR (20011, 16, -1)
  2238.             RETURN (1)
  2239.     END
  2240.  
  2241.     -- SyncTran
  2242.     /*
  2243.     ** Parameter Check:  @allow_sync_tran
  2244.     */
  2245.  
  2246.     IF @allow_sync_tran IS NULL OR LOWER(@allow_sync_tran) NOT IN ('true', 'false')
  2247.     BEGIN
  2248.         RAISERROR (14148, 16, -1, '@allow_sync_tran')
  2249.         RETURN (1)
  2250.     END
  2251.  
  2252.     /*
  2253.     ** Parameter Check:  @allow_queued_tran
  2254.     */
  2255.  
  2256.     IF @allow_queued_tran IS NULL OR LOWER(@allow_queued_tran) NOT IN ('true', 'false')
  2257.     BEGIN
  2258.         RAISERROR (14148, 16, -1, '@allow_queued_tran')
  2259.         RETURN (1)
  2260.     END
  2261.  
  2262.     IF LOWER(@allow_sync_tran) = 'true' 
  2263.     BEGIN
  2264.         -- If we are doing sync tran, we need independent agents
  2265.         -- override the user input
  2266.         SELECT @allow_sync_tran_id = 1
  2267.             ,@independent_agent = 'true'
  2268.             ,@independent_agent_id = 1
  2269.             ,@backward_comp_level = 40 -- immediate update needs to have the new sp_addsynctriggers stored proc
  2270.     END
  2271.     ELSE 
  2272.     BEGIN
  2273.         SELECT @allow_sync_tran_id = 0
  2274.     END
  2275.  
  2276.     IF LOWER(@allow_queued_tran) = 'true' 
  2277.     BEGIN
  2278.         -- If we are doing queued tran, we need independent agents
  2279.         -- override the user input
  2280.         SELECT @allow_queued_tran_id = 1
  2281.             ,@independent_agent = 'true'
  2282.             ,@independent_agent_id = 1
  2283.             ,@backward_comp_level = 40 -- queued compenents not avaliable prior to shiloh
  2284.     END
  2285.     ELSE 
  2286.     BEGIN
  2287.         SELECT @allow_queued_tran_id = 0
  2288.     END
  2289.  
  2290.     --Parameter Check:  @autogen_sync_procs
  2291.     IF @autogen_sync_procs IS NULL OR LOWER(@autogen_sync_procs) NOT IN ('true', 'false')
  2292.     BEGIN                                 
  2293.         RAISERROR (14148, 16, -1, '@autogen_sync_procs')
  2294.         RETURN (1)
  2295.     END
  2296.  
  2297.     --
  2298.     -- For publications that allow updating subscribers (immediate/queued)
  2299.     -- this option has to be true at all times, for others
  2300.     -- it should be false. This flag is not of any value currently
  2301.     -- as we do not have any provision for accepting custom generated
  2302.     -- synctan proc names for an article. For now, we will override
  2303.     -- the user supplied value
  2304.     --
  2305.     select @autogen_sync_procs_id = case 
  2306.         when (@allow_sync_tran_id = 0 and @allow_queued_tran_id = 0) then 0
  2307.         else 1
  2308.     end
  2309.     
  2310.     -- Portable snapshot
  2311.     IF @snapshot_in_defaultfolder IS NULL OR LOWER(@snapshot_in_defaultfolder) NOT IN ('true', 'false')
  2312.     BEGIN
  2313.         RAISERROR (14148, 16, -1, '@snapshot_in_defaultfolder')
  2314.         RETURN (1)
  2315.     END
  2316.     
  2317.     IF LOWER(@snapshot_in_defaultfolder) = 'true'
  2318.     BEGIN
  2319.         SELECT @snapshot_in_defaultfolder_bit = 1
  2320.     END
  2321.     ELSE
  2322.     BEGIN
  2323.         SELECT @snapshot_in_defaultfolder_bit = 0
  2324.     END
  2325.  
  2326.     -- Pre/Post snapshot commands
  2327.     -- If @sync_method is character mode bcp, this would indicate that
  2328.     -- this publication may support non-SQL Server subscribers. In this 
  2329.     -- case, pre- and post- snapshot commands are not allowed.
  2330.     IF @smid = 1 AND 
  2331.         ((@pre_snapshot_script IS NOT NULL AND @pre_snapshot_script <> '') OR
  2332.          (@post_snapshot_script IS NOT NULL AND @post_snapshot_script <> ''))
  2333.     BEGIN
  2334.         RAISERROR (21151, 16, -1)
  2335.         RETURN (1)
  2336.     END
  2337.     
  2338.     -- Parameter check - @compress_snapshot
  2339.     -- @compress_snapshot can be 1 if @alt_snapshot_folder is non-null
  2340.     IF LOWER(@compress_snapshot) NOT IN ('true', 'false')
  2341.     BEGIN
  2342.         RAISERROR (14148, 16, -1, '@compress_snapshot')
  2343.         RETURN (1)
  2344.     END
  2345.     
  2346.     IF LOWER(@compress_snapshot) = 'true'
  2347.     BEGIN
  2348.         SELECT @compress_snapshot_bit = 1
  2349.     END
  2350.     ELSE
  2351.     BEGIN
  2352.         SELECT @compress_snapshot_bit = 0
  2353.     END
  2354.  
  2355.     -- Snapshot compression can only be enabled if an alternate 
  2356.     -- snapshot generation folder exists or the publication
  2357.     -- is enabled for internet.
  2358.     IF (@compress_snapshot_bit = 1 AND 
  2359.         (@alt_snapshot_folder IS NULL OR @alt_snapshot_folder = N'') AND
  2360.         (LOWER(@enabled_for_internet) = N'false'))
  2361.     BEGIN
  2362.         RAISERROR (21157, 16, -1)
  2363.         RETURN (1)
  2364.     END    
  2365.  
  2366.     -- Parameter check: ftp_address
  2367.     -- If the publication is enabled for internet, ftp_address cannot be null
  2368.     IF @enabled_for_internet_id = 1 AND (@ftp_address IS NULL OR @ftp_address = N'')
  2369.     BEGIN
  2370.         RAISERROR (21158, 16, -1)
  2371.         RETURN (1)
  2372.     END     
  2373.  
  2374.     -- Parameter check: ftp_port
  2375.     IF @ftp_port IS NULL
  2376.     BEGIN
  2377.         RAISERROR (21160, 16, -1)
  2378.     END
  2379.  
  2380.     -- Parameter check : DTS
  2381.     declare @allow_dts_id bit
  2382.     IF @allow_dts IS NULL OR LOWER(@allow_dts) NOT IN ('true', 'false')
  2383.     BEGIN
  2384.         RAISERROR (14148, 16, -1, '@allow_dts')
  2385.         RETURN (1)
  2386.     END
  2387.  
  2388.     -- Encrypt ftp password before putting it into the syspublications
  2389.     -- table if one is provided
  2390.     SELECT @enc_ftp_password = NULL
  2391.     IF @ftp_password IS NOT NULL
  2392.     BEGIN
  2393.         SELECT @enc_ftp_password = @ftp_password 
  2394.         EXEC @retcode = master.dbo.xp_repl_encrypt @enc_ftp_password OUTPUT
  2395.         IF @retcode <> 0
  2396.         BEGIN
  2397.             RETURN (1)
  2398.         END
  2399.     END    
  2400.  
  2401.     IF LOWER(@allow_dts) = 'true' SELECT @allow_dts_id = 1
  2402.     ELSE SELECT @allow_dts_id = 0
  2403.  
  2404.     -- To allow DTS, the publication has to be
  2405.     -- 1. independent agent
  2406.     -- 2. char bcp
  2407.  
  2408.     if @allow_dts_id = 1
  2409.     begin
  2410.         if @smid NOT IN ( 1, 4 )
  2411.         begin
  2412.             -- 'The publication has to be in char bcp mode.'
  2413.             raiserror(21172, 16, -1)
  2414.             return(1)
  2415.         end
  2416.         if @independent_agent_id = 0
  2417.         begin
  2418.             -- 'The publication has to be independent agent.'
  2419.             raiserror(21173, 16, -1)
  2420.             return(1)        
  2421.         end
  2422.         if @allow_sync_tran_id = 1 or @allow_queued_tran_id = 1
  2423.         begin
  2424.             raiserror(21180, 16, -1)
  2425.             return(1)
  2426.         end
  2427.     end
  2428.  
  2429.     declare @allow_subscription_copy_id bit
  2430.     IF LOWER(@allow_subscription_copy) = 'true' SELECT @allow_subscription_copy_id = 1
  2431.     ELSE SELECT @allow_subscription_copy_id = 0
  2432.  
  2433.     -- To allow subscription copy, the publication has to be
  2434.     -- 1. immediate_sync
  2435.     if @allow_subscription_copy_id = 1
  2436.     begin
  2437.         if @immediate_sync_id <> 1
  2438.         begin
  2439.             raiserror(21210, 16, -1)
  2440.             return(1)
  2441.         end
  2442.     end
  2443.  
  2444.     --
  2445.     -- Check parameters for @conflict_policy, @centralized_conflicts, @conflict_retention
  2446.     -- for queued publications
  2447.     --
  2448.     if (@allow_queued_tran_id = 1)
  2449.     begin
  2450.         --
  2451.         -- set default conflict_policy if required
  2452.         --
  2453.         if (@conflict_policy IS NULL)
  2454.         begin
  2455.             --
  2456.             -- if it is snapshot based, then the default policy is 'sub reinit'
  2457.             -- else the default policy is 'pub wins'
  2458.             --
  2459.             select @conflict_policy = case when (@rfid = 1) then 'sub reinit' 
  2460.                                         else 'pub wins' end
  2461.         end
  2462.         
  2463.         if (LOWER(@conflict_policy) = 'sub reinit')
  2464.             select @conflict_policy_id = 3
  2465.         else if (LOWER(@conflict_policy) = 'pub wins')
  2466.             select @conflict_policy_id = 1
  2467.         else if (LOWER(@conflict_policy) = 'sub wins')
  2468.             select @conflict_policy_id = 2
  2469.         else
  2470.         begin
  2471.             raiserror (21184, 16, 2, '@conflict_policy', 'sub reinit', 'pub wins', 'sub wins')
  2472.             return (1)
  2473.         end
  2474.  
  2475.         --
  2476.         -- Check snapshot permissible values
  2477.         --
  2478.         if ((@rfid = 1) and (@conflict_policy_id = 1))
  2479.         begin
  2480.             raiserror (21270, 16, 1, '@conflict_policy', @conflict_policy)
  2481.             return (1)
  2482.         end
  2483.         
  2484.         --
  2485.         -- set default centralized_conflicts if required
  2486.         --
  2487.         if (@centralized_conflicts IS NULL)
  2488.             select @centralized_conflicts = 'true'
  2489.         
  2490.         if (LOWER(@centralized_conflicts) = 'true')
  2491.             select @centralized_conflicts_bit = 1
  2492.         else if (LOWER(@centralized_conflicts) = 'false')
  2493.             select @centralized_conflicts_bit = 0
  2494.         else
  2495.         begin
  2496.             raiserror (14148, 16, -1, '@centralized_conflicts')
  2497.             return (1)
  2498.         end
  2499.  
  2500.         --
  2501.         -- Check snapshot permissible values
  2502.         --
  2503.         if ((@rfid = 1) and (@centralized_conflicts_bit = 0))
  2504.         begin
  2505.             raiserror (21270, 16, 1, '@centralized_conflicts', @centralized_conflicts)
  2506.             return (1)
  2507.         end
  2508.         
  2509.         if (@conflict_retention IS NULL)
  2510.             select @conflict_retention = 14
  2511.         else if (@conflict_retention < 0)
  2512.         begin
  2513.             raiserror(20050, 16, -1, 0)
  2514.             return (1)
  2515.         end
  2516.  
  2517.         if ((@queue_type IS NULL) or (LOWER(@queue_type) = 'sql'))
  2518.             select @queue_type_val = 2
  2519.         else if (LOWER(@queue_type) = 'msmq')
  2520.             select @queue_type_val = 1
  2521.         else
  2522.         begin
  2523.             raiserror (21184, 16, 3, '@queue_type', 'msmq', 'sql', 'NULL')
  2524.             return (1)
  2525.         end
  2526.     end
  2527.  
  2528.     /*
  2529.     ** Get distribution server information for remote RPC call.
  2530.     */
  2531.     EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  2532.        @distribdb   = @distribdb OUTPUT
  2533.     IF @@ERROR <> 0 or @retcode <> 0
  2534.     BEGIN
  2535.         GOTO UNDO
  2536.     END
  2537.  
  2538.     /*
  2539.     **  Add publication to syspublications.
  2540.     */
  2541.     begin tran
  2542.     save TRAN sp_addpublication
  2543.  
  2544.     select @dbname = db_name()
  2545.     
  2546.     /*
  2547.     ** Construct Log Reader agent name.
  2548.     */
  2549.  
  2550.     declare @job_existing bit
  2551.  
  2552.     -- Create logreader task for the first log based or allow queued publication.
  2553.     -- We need logreader for queued publication to do idenity range management.
  2554.     IF  (@rfid = 0 or @allow_queued_tran_id = 1)  and NOT EXISTS 
  2555.         (SELECT * FROM syspublications where repl_freq = 0 or allow_queued_tran = 1) 
  2556.     BEGIN
  2557.         -- Clear repl dbtable fields. This will avoid unnecessary log scan in the 
  2558.         -- logreader at the first time it runs.
  2559.         --
  2560.         -- sp_droppublication will clear the fields when dropping the last publication, 
  2561.         -- however, it is after the transaction deleting syspublication table being
  2562.         -- committed, thus not guaranteed.
  2563.         -- 
  2564.         -- We also need this logic for upgraded 7.0 databases where we don't clear
  2565.         -- distbackuplsn and distlastlsn fields in unpublishing.
  2566.         --
  2567.         /* ensure we can get in as logreader */
  2568.         exec @retcode = dbo.sp_replflush
  2569.         IF @@ERROR <> 0 or @retcode <> 0
  2570.             GOTO UNDO
  2571.  
  2572.         /* unmark all xacts marked for replication */
  2573.         exec @retcode = dbo.sp_repldone NULL, NULL, 0, 0, 1
  2574.         IF @@ERROR <> 0 or @retcode <> 0
  2575.             GOTO UNDO
  2576.     
  2577.         /* release our hold on the db as logreader */
  2578.         EXEC @retcode = dbo.sp_replflush
  2579.         IF @@ERROR <> 0 or @retcode <> 0
  2580.             GOTO UNDO
  2581.  
  2582.         -- Run checkpoint to make sp_repldone result durable (write repl dbtable fields
  2583.         -- into the checkpoint record).
  2584.         checkpoint
  2585.         IF @@ERROR <> 0
  2586.             GOTO UNDO
  2587.  
  2588.  
  2589.         if @logreader_job_name is null
  2590.             select @job_existing = 0
  2591.         else
  2592.             select @job_existing = 1
  2593.  
  2594.         /*
  2595.         ** Schedule Log Reader agent for the database
  2596.         ** If @logreader_job_name is not null
  2597.         */
  2598.         SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb +'.dbo.sp_MSadd_logreader_agent'
  2599.  
  2600.         EXECUTE @retcode = @distproc
  2601.             @name = @logreader_job_name,
  2602.             @publisher = @@SERVERNAME,
  2603.             @publisher_db = @dbname,
  2604.             @publication = 'ALL',  
  2605.             @local_job = 1,
  2606.             @job_existing = @job_existing 
  2607.  
  2608.         IF @@ERROR <> 0 or @retcode <> 0
  2609.             GOTO UNDO
  2610.     END            
  2611.  
  2612.     INSERT syspublications(description, name, repl_freq,
  2613.                            status, sync_method, snapshot_jobid, independent_agent,
  2614.                            immediate_sync, enabled_for_internet, 
  2615.                            allow_push, allow_pull, allow_anonymous, immediate_sync_ready,
  2616.                            -- SyncTran
  2617.                            allow_sync_tran, autogen_sync_procs, retention, allow_queued_tran,
  2618.                            snapshot_in_defaultfolder, alt_snapshot_folder, pre_snapshot_script, 
  2619.                            post_snapshot_script, compress_snapshot, ftp_address, ftp_port, 
  2620.                            ftp_subdirectory, ftp_login, ftp_password, allow_dts, 
  2621.                            allow_subscription_copy, centralized_conflicts, conflict_retention, 
  2622.                            conflict_policy, queue_type, backward_comp_level)
  2623.  
  2624.     VALUES (@description, @publication, @rfid, @statid, @smid, NULL, 
  2625.             @independent_agent_id, 
  2626.             @immediate_sync_id, @enabled_for_internet_id, @allow_push_id,
  2627.             @allow_pull_id, @allow_anonymous_id, 0,
  2628.             -- SyncTran
  2629.             @allow_sync_tran_id, @autogen_sync_procs_id, @retention, @allow_queued_tran_id,
  2630.             @snapshot_in_defaultfolder_bit, @alt_snapshot_folder, @pre_snapshot_script,
  2631.             @post_snapshot_script, @compress_snapshot_bit, @ftp_address, @ftp_port, 
  2632.             @ftp_subdirectory, @ftp_login, @enc_ftp_password, 
  2633.             @allow_dts_id, @allow_subscription_copy_id, @centralized_conflicts_bit, @conflict_retention, 
  2634.             @conflict_policy_id, @queue_type_val, @backward_comp_level)
  2635.  
  2636.     IF @@ERROR <> 0
  2637.     BEGIN
  2638.         RAISERROR (14018, 16, -1)
  2639.         GOTO UNDO
  2640.     END
  2641.  
  2642.     SELECT @pubid = @@IDENTITY
  2643.  
  2644.     DECLARE @false bit
  2645.     SELECT @false = 0
  2646.  
  2647.     DECLARE @null sysname
  2648.     SELECT @null = NULL
  2649.  
  2650.     /*
  2651.     ** Add the publication to the distributor side
  2652.     */
  2653.     SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  2654.         '.dbo.sp_MSadd_publication'
  2655.     EXECUTE @retcode = @distproc
  2656.     @publisher = @@SERVERNAME,
  2657.     @publisher_db = @dbname,
  2658.     @publication = @publication,
  2659.     @publication_type = @rfid,
  2660.     @independent_agent = @independent_agent_id,
  2661.     @immediate_sync = @immediate_sync_id,
  2662.     @allow_push = @allow_push_id,
  2663.     @allow_pull = @allow_pull_id,
  2664.     @allow_anonymous = @allow_anonymous_id,
  2665.     @snapshot_agent = @null,
  2666.     @logreader_agent = @agentname,
  2667.     @description = @description,
  2668.     @retention = @retention,
  2669.     @sync_method = @smid,
  2670.     @allow_subscription_copy = @allow_subscription_copy_id,
  2671.     @allow_queued_tran = @allow_queued_tran_id,
  2672.     @queue_type = @queue_type_val
  2673.  
  2674.     IF @@ERROR <> 0 or @retcode <> 0
  2675.         BEGIN
  2676.             GOTO UNDO
  2677.         END
  2678.  
  2679.     if @qreader_job_name is not null
  2680.     begin
  2681.         --
  2682.         -- Schedule Queue Reader agent for the database
  2683.         --
  2684.         SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb +'.dbo.sp_MSadd_qreader_agent'
  2685.         EXECUTE @retcode = @distproc @name = @qreader_job_name
  2686.         IF @@ERROR <> 0 or @retcode <> 0
  2687.         GOTO UNDO
  2688.     end    
  2689.  
  2690.     -- Populate the initial list.
  2691.     exec @retcode = dbo.sp_grant_publication_access 
  2692.         @publication = @publication,
  2693.         @login = null,
  2694.         @reserved = 'init'
  2695.     IF @@error <> 0 OR @retcode <> 0
  2696.         GOTO UNDO
  2697.  
  2698.     COMMIT TRAN
  2699.  
  2700.     declare @returnstring nvarchar(512) 
  2701.     set @returnstring = N''
  2702.     if LOWER(@add_to_active_directory)='true'
  2703.     begin
  2704.         --no error checking needed here.    
  2705.         create table #guid_name_for_active_directory(ad_guidname sysname collate database_default null)
  2706.         if @@ERROR<>0
  2707.         begin
  2708.             goto FAILURE                     
  2709.         end
  2710.         insert into #guid_name_for_active_directory exec @retcode=master.dbo.sp_ActiveDirectory_Obj 'CREATE', 'PUBLICATION', @publication, @dbname
  2711.         if @retcode <> 0 or @@ERROR<>0
  2712.         begin
  2713.             set @returnstring = (select TOP 1 ad_guidname from #guid_name_for_active_directory)
  2714.             goto FAILURE                     
  2715.            end
  2716.         select TOP 1 @ad_guidname = ad_guidname from #guid_name_for_active_directory
  2717.         if @ad_guidname is not NULL
  2718.         begin
  2719.             update syspublications set ad_guidname=@ad_guidname where pubid=@pubid
  2720.             if @@ERROR<>0
  2721.                 goto FAILURE
  2722.         end
  2723.         drop table #guid_name_for_active_directory
  2724.     end
  2725.     RETURN(0)
  2726. FAILURE:
  2727.     drop table #guid_name_for_active_directory
  2728.     if @returnstring is NULL
  2729.         select @returnstring = N''
  2730.     raiserror(21363, 16, -1, @publication, @returnstring)
  2731.     return (1)   
  2732. UNDO:
  2733.     IF @@TRANCOUNT > 0
  2734.     begin
  2735.         ROLLBACK TRAN sp_addpublication
  2736.         COMMIT TRAN   
  2737.     end
  2738.     return 1
  2739. END
  2740. go
  2741.  
  2742. EXEC dbo.sp_MS_marksystemobject sp_addpublication
  2743. GO
  2744.  
  2745. print ''
  2746. print 'Creating procedure sp_changepublication'
  2747. go
  2748.  
  2749. CREATE PROCEDURE sp_changepublication (
  2750.     @publication sysname = NULL,        /* Publication name */
  2751.     @property nvarchar(50) = NULL,           /* The property to change */
  2752.     @value nvarchar(255) = NULL,              /* The new property value */
  2753.     @force_invalidate_snapshot bit = 0,    /* Force invalidate existing snapshot */
  2754.     @force_reinit_subscription bit = 0    /* Force reinit subscription */
  2755. AS
  2756. BEGIN
  2757.     SET NOCOUNT ON
  2758.  
  2759.     /*
  2760.     ** Declarations.
  2761.     */
  2762.  
  2763.     DECLARE @cmd nvarchar(255)
  2764.             ,@cmd2 nvarchar(255)
  2765.             ,@pubid int
  2766.             ,@replfreqid tinyint
  2767.             ,@retcode int
  2768.             ,@statusid tinyint
  2769.             ,@syncmethodid tinyint
  2770.             ,@db_name    sysname
  2771.             ,@distributor sysname
  2772.             ,@distproc nvarchar (255)
  2773.             ,@subscribed int    
  2774.             ,@virtual_id smallint
  2775.             ,@prev_value_bit bit
  2776.             ,@value_bit bit
  2777.             ,@allow_anonymous bit
  2778.             ,@push int
  2779.             ,@pull int
  2780.             ,@independent_agent bit
  2781.             ,@immediate_sync bit
  2782.             ,@distribdb sysname
  2783.             ,@dbname sysname
  2784.             ,@taskid int
  2785.             ,@add_virtual_back bit
  2786.             ,@alt_snapshot_folder nvarchar(255)
  2787.             ,@enabled_for_internet bit
  2788.             ,@ftp_address sysname
  2789.             ,@snapshot_in_defaultfolder bit
  2790.             ,@allow_dts bit
  2791.             ,@in_ActiveD    bit
  2792.             ,@ad_guidname    sysname
  2793.             ,@enc_ftp_password nvarchar(524)
  2794.             ,@conflict_policy_id int
  2795.             ,@centralized_conflicts_bit bit
  2796.             ,@conflict_retention int
  2797.             ,@queue_type int
  2798.             ,@allow_sync_tran bit
  2799.             ,@allow_queued_tran bit
  2800.             
  2801.     SELECT @add_virtual_back = 0
  2802.             ,@push = 0
  2803.             ,@pull = 1
  2804.             ,@alt_snapshot_folder = NULL
  2805.             ,@subscribed = 1
  2806.             ,@virtual_id = -1
  2807.  
  2808.     /*
  2809.     ** Security Check
  2810.     */
  2811.  
  2812.     exec @retcode = dbo.sp_MSreplcheck_publish
  2813.     if @@ERROR <> 0 or @retcode <> 0
  2814.         return(1)
  2815.  
  2816.     /*
  2817.     ** Check to see if the database has been activated for publication.
  2818.     */
  2819.  
  2820.     IF (SELECT category & 1
  2821.           FROM master..sysdatabases
  2822.          WHERE name = DB_NAME() collate database_default) = 0
  2823.  
  2824.     BEGIN
  2825.         RAISERROR (14013, 16, -1)
  2826.         RETURN (1)
  2827.     END
  2828.  
  2829.     select @db_name=db_name()
  2830.     
  2831.     /*
  2832.     ** Parameter Check:  @property.
  2833.     ** If the @property parameter is NULL, print the options.
  2834.     */
  2835.  
  2836.     IF @property IS NULL
  2837.         BEGIN
  2838.             CREATE TABLE #tab1 (properties sysname collate database_default not null)
  2839.             INSERT INTO #tab1 VALUES ('description')
  2840.             --INSERT INTO #tab1 VALUES ('taskid')
  2841.             INSERT INTO #tab1 VALUES ('sync_method')
  2842.             INSERT INTO #tab1 VALUES ('status')
  2843.             INSERT INTO #tab1 VALUES ('repl_freq')
  2844.             INSERT INTO #tab1 VALUES ('independent_agent')
  2845.             INSERT INTO #tab1 VALUES ('immediate_sync')
  2846.             INSERT INTO #tab1 VALUES ('enabled_for_internet')
  2847.             INSERT INTO #tab1 VALUES ('allow_push')
  2848.             INSERT INTO #tab1 VALUES ('allow_pull')
  2849.             INSERT INTO #tab1 VALUES ('allow_anonymous')
  2850.             INSERT INTO #tab1 VALUES ('retention')
  2851.             INSERT INTO #tab1 VALUES ('snapshot_in_defaultfolder')
  2852.             INSERT INTO #tab1 VALUES ('alt_snapshot_folder')
  2853.             INSERT INTO #tab1 VALUES ('pre_snapshot_script')
  2854.             INSERT INTO #tab1 VALUES ('post_snapshot_script')
  2855.             INSERT INTO #tab1 VALUES ('compress_snapshot')
  2856.             INSERT INTO #tab1 VALUES ('ftp_address')
  2857.             INSERT INTO #tab1 VALUES ('ftp_port')
  2858.             INSERT INTO #tab1 VALUES ('ftp_subdirectory')
  2859.             INSERT INTO #tab1 VALUES ('ftp_login')
  2860.             INSERT INTO #tab1 VALUES ('ftp_password')
  2861.             INSERT INTO #tab1 VALUES ('allow_subscription_copy')
  2862.             INSERT INTO #tab1 VALUES ('conflict_policy')
  2863.             INSERT INTO #tab1 VALUES ('centralized_conflicts')
  2864.             INSERT INTO #tab1 VALUES ('conflict_retention')
  2865.             INSERT INTO #tab1 VALUES ('queue_type')
  2866.             INSERT INTO #tab1 VALUES ('publish_to_ActiveDirectory')
  2867.             PRINT ''
  2868.             SELECT * FROM #tab1
  2869.             RETURN (0)
  2870.         END
  2871.  
  2872.     /*
  2873.     ** Parameter Check:  @publication.
  2874.     ** Make sure that the publication exists.
  2875.     */
  2876.  
  2877.     IF @publication IS NULL
  2878.         BEGIN
  2879.             RAISERROR (14043, 16, -1, '@publication')
  2880.             RETURN (1)
  2881.         END
  2882.  
  2883.     EXECUTE @retcode = dbo.sp_validname @publication
  2884.  
  2885.     IF @@ERROR <> 0 OR @retcode <> 0
  2886.     RETURN (1)
  2887.  
  2888.     SELECT @allow_anonymous = allow_anonymous, @pubid = pubid, 
  2889.         @ad_guidname=ad_guidname, --with NULL value if this publication is not in AD
  2890.         @replfreqid = repl_freq,
  2891.         @immediate_sync = immediate_sync,
  2892.         @independent_agent = independent_agent,
  2893.         @syncmethodid = sync_method,
  2894.         @alt_snapshot_folder = alt_snapshot_folder,
  2895.         @enabled_for_internet = enabled_for_internet,
  2896.         @ftp_address = ftp_address,
  2897.         @allow_dts = allow_dts
  2898.         ,@queue_type = queue_type
  2899.         ,@snapshot_in_defaultfolder = snapshot_in_defaultfolder
  2900.         ,@in_ActiveD = case when ad_guidname is NULL then 0 else 1 end 
  2901.         ,@allow_sync_tran = allow_sync_tran
  2902.         ,@allow_queued_tran = allow_queued_tran
  2903.         FROM syspublications 
  2904.         WHERE name = @publication
  2905.  
  2906.     IF @pubid IS NULL
  2907.         BEGIN
  2908.             RAISERROR (20026, 11, -1, @publication)
  2909.             RETURN (1)
  2910.         END
  2911.     ELSE
  2912.  
  2913.     /*
  2914.     ** Parameter Check:  @property.
  2915.     ** Check to make sure that @property is a valid property in
  2916.     ** syspublications.
  2917.     */
  2918.  
  2919.     IF LOWER(@property) NOT IN ( 'taskid','description', 'sync_method',
  2920.      'status', 'repl_freq','immediate_sync', 'independent_agent', 
  2921.      'enabled_for_internet', 'allow_push', 'allow_pull', 'allow_anonymous', 'retention',
  2922.      'snapshot_in_defaultfolder', 'alt_snapshot_folder', 'pre_snapshot_script', 'post_snapshot_script', 
  2923.      'compress_snapshot', 'ftp_address', 'ftp_port', 'ftp_subdirectory',
  2924.      'ftp_login', 'ftp_password','allow_subscription_copy','conflict_policy',
  2925.      'centralized_conflicts','conflict_retention','queue_type','publish_to_activedirectory')
  2926.         BEGIN
  2927.             RAISERROR (21183, 16, -1, @property)
  2928.             RETURN (1)
  2929.         END
  2930.  
  2931.     /*
  2932.     ** Parameter Check:
  2933.     ** If sync_method of the publication is character mode (an indication that it supports
  2934.     ** third party Subscribers), pre/post-snapshot setting must be null   
  2935.     **
  2936.     */
  2937.     IF @syncmethodid = 1 
  2938.     BEGIN
  2939.         IF (LOWER(@property) = 'pre_snapshot_script' OR
  2940.             LOWER(@property) = 'post_snapshot_script') AND
  2941.             @value IS NOT NULL AND @value <> ''
  2942.         BEGIN
  2943.             RAISERROR (21151, 16, -1)
  2944.             RETURN (1)
  2945.         END   
  2946.     END
  2947.  
  2948.     /*
  2949.     ** Parameter Check:
  2950.     ** If the Publication's alt_snapshot_folder setting is null, 
  2951.     ** snapshot compression cannot be enabled
  2952.     */
  2953.     IF (@alt_snapshot_folder IS NULL OR @alt_snapshot_folder = '') 
  2954.         AND LOWER(@property) = 'compress_snapshot'
  2955.         AND LOWER(@value) = 'true'   
  2956.     BEGIN
  2957.         RAISERROR (21157, 16, -1)        
  2958.         RETURN(1)
  2959.     END
  2960.  
  2961.     /* 
  2962.     ** Parameter Check:
  2963.     ** If enabled_for_internet is set to true, the publication must have a non-null
  2964.     ** ftp_address.
  2965.     */
  2966.     IF LOWER(@property) = N'enabled_for_internet' AND
  2967.        LOWER(@value) = N'true' AND 
  2968.        (@ftp_address IS NULL OR @ftp_address = N'')
  2969.     BEGIN
  2970.         RAISERROR(21158, 16, -1)
  2971.         RETURN (1)
  2972.     END
  2973.  
  2974.     /*
  2975.     ** .. and ftp_address cannot be null if the publication is enabled for 
  2976.     ** internet.
  2977.     */
  2978. /*
  2979.     IF @enabled_for_internet = 1 AND
  2980.       (LOWER(@property) = N'ftp_address'
  2981.         AND (@value IS NULL OR @value = N''))
  2982.     BEGIN
  2983.         RAISERROR(21158, 16, -1)
  2984.         RETURN (1)
  2985.     END
  2986. */
  2987.     /*
  2988.     ** .. and 'alternate snapshot folder' is not null
  2989.     **
  2990.     */
  2991.     IF LOWER(@property) = N'enabled_for_internet' AND
  2992.         LOWER(@value) = N'true' AND
  2993.        (@alt_snapshot_folder IS NULL OR @alt_snapshot_folder = N'')
  2994.     BEGIN
  2995.         RAISERROR(21159, 16, -1)
  2996.         RETURN (1)
  2997.     END 
  2998.  
  2999.     /* 
  3000.     ** Parameter Check:
  3001.     ** If the publication is enabled for internet, the publication must
  3002.     ** have a non-null alternate snapshot folder and the 
  3003.     ** snapshot_in_defaultfolder property must be 0.
  3004.     */
  3005. /*
  3006.     IF @enabled_for_internet = 1 AND 
  3007.        ((LOWER(@property) = N'alt_snapshot_folder'
  3008.         AND (@value IS NULL OR @value = N'')))
  3009.     BEGIN
  3010.         RAISERROR(21159, 16, -1)
  3011.         RETURN (1)
  3012.     END  
  3013. */
  3014.  
  3015.     /*
  3016.     ** Parameter Check:
  3017.     ** 'ftp_port' cannot be null
  3018.     */
  3019.     IF LOWER(@property) = N'ftp_port' AND @value IS NULL
  3020.     BEGIN
  3021.         RAISERROR (14043, 16, -1, @property)
  3022.         RETURN (1)
  3023.     END
  3024.  
  3025.     -- Check to see if there are snapshot and subscription needs to be reinited.
  3026.     declare @need_new_snapshot bit
  3027.         ,@need_reinit_subscription bit
  3028.         ,@active tinyint
  3029.  
  3030.     select @active = 2
  3031.     select @need_new_snapshot = 0
  3032.     select @need_reinit_subscription = 0
  3033.  
  3034.     if LOWER(@property) in ('snapshot_in_defaultfolder', 'alt_snapshot_folder',
  3035.         'pre_snapshot_script', 'post_snapshot_script', 'compress_snapshot', 
  3036.         'ftp_address','ftp_port','ftp_subdirectory','ftp_login','ftp_password',
  3037.         'enabled_for_internet')
  3038.     begin
  3039.         select @need_new_snapshot = 1
  3040.     end
  3041.     else if LOWER(@property) = 'sync_method'
  3042.     begin
  3043.         -- If changing to or from concurrent, must reinit subscription.
  3044.         if EXISTS( select * from syspublications sp
  3045.             where sp.pubid = @pubid and 
  3046.             (sp.sync_method in (3,4) or LOWER(@value) in ('concurrent', 'concurrent_c'))) 
  3047.         BEGIN
  3048.             select @need_new_snapshot = 1
  3049.             select @need_reinit_subscription = 1            
  3050.         END
  3051.         else
  3052.             select @need_new_snapshot = 1
  3053.     end
  3054.     else if LOWER(@property) = 'repl_freq'
  3055.     BEGIN
  3056.         select @need_new_snapshot = 1
  3057.         select @need_reinit_subscription = 1            
  3058.     END
  3059.     
  3060.     -- Have to call this stored procedure to invalidate existing snapshot or reint
  3061.     -- subscriptions if needed
  3062.     EXECUTE @retcode  = dbo.sp_MSreinit_article
  3063.         @publication = @publication, 
  3064.         @need_new_snapshot = @need_new_snapshot,
  3065.         @need_reinit_subscription = @need_reinit_subscription
  3066.         ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  3067.         ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  3068.         ,@check_only = 1
  3069.     IF @@ERROR <> 0 OR @retcode <> 0
  3070.         return (1)
  3071.  
  3072.     /*
  3073.     ** Change the property.
  3074.     */
  3075.     begin tran
  3076.     save TRAN sp_changepublication
  3077.  
  3078.     IF LOWER(@property) ='description'
  3079.         BEGIN
  3080.             UPDATE syspublications SET description = @value
  3081.                 WHERE pubid = @pubid
  3082.             IF @@ERROR <> 0 GOTO UNDO
  3083.         END
  3084.         
  3085.     IF LOWER(@property) ='retention'
  3086.         BEGIN
  3087.             if @value is NULL 
  3088.                 BEGIN
  3089.                     RAISERROR(20081, 16, -1, @property)
  3090.                     GOTO UNDO
  3091.                 END
  3092.                 
  3093.             UPDATE syspublications SET retention = convert(int, @value)
  3094.                 WHERE pubid = @pubid
  3095.             IF @@ERROR <> 0 GOTO UNDO
  3096.         END
  3097.    
  3098.  
  3099.    if LOWER(@property) = 'publish_to_activedirectory'
  3100.            BEGIN
  3101.         if LOWER(@value) NOT IN ('true', 'false')
  3102.             BEGIN
  3103.                 RAISERROR (14137, 16, -1)
  3104.                 GOTO UNDO
  3105.             END
  3106.  
  3107.         /* Is AD supported? */
  3108.         DECLARE @retval  INT
  3109.         EXECUTE @retval = master.dbo.xp_MSADEnabled
  3110.         if (@retval <> 0)
  3111.         begin
  3112.             RAISERROR(21254, 16, -1, @publication)
  3113.             RETURN (1)
  3114.         end
  3115.  
  3116.            if @in_ActiveD=0 and LOWER(@value)='true'
  3117.                BEGIN
  3118.                 create table #guid_name_for_active_directory(ad_guidname sysname collate database_default null)
  3119.                 if @@ERROR<>0
  3120.                 begin
  3121.                     raiserror(21363, 16, -1, @publication, N'')
  3122.                     GOTO UNDO                                    
  3123.                 end
  3124.                 insert into #guid_name_for_active_directory exec @retcode=master.dbo.sp_ActiveDirectory_Obj 'CREATE', 'PUBLICATION', @publication, @db_name
  3125.                 if @retcode <> 0 or @@ERROR<>0
  3126.                 begin
  3127.                     declare @errorstring nvarchar(512)
  3128.                     select @errorstring = (select TOP 1 ad_guidname from #guid_name_for_active_directory) 
  3129.                     drop table #guid_name_for_active_directory
  3130.                     if @errorstring is NULL
  3131.                         select @errorstring=N''
  3132.                     raiserror(21363, 16, -1, @publication, @errorstring)
  3133.                     GOTO UNDO                    
  3134.                    end
  3135.                 select TOP 1 @ad_guidname = ad_guidname from #guid_name_for_active_directory
  3136.  
  3137.                 if @ad_guidname is not NULL
  3138.                 begin
  3139.                     update syspublications set ad_guidname=@ad_guidname where pubid=@pubid
  3140.                     if @@ERROR<>0
  3141.                     begin
  3142.                         drop table #guid_name_for_active_directory
  3143.                         raiserror(21363, 16, -1, @publication, N'')
  3144.                         GOTO UNDO                    
  3145.                     end
  3146.                 end
  3147.                 drop table #guid_name_for_active_directory
  3148.                END
  3149.            else if @in_ActiveD=1 and LOWER(@value)='false'
  3150.                BEGIN
  3151.                 exec @retcode=master.dbo.sp_ActiveDirectory_Obj 'DELETE', 'PUBLICATION', @publication, @db_name, @ad_guidname
  3152.                 if @@ERROR<>0 or @retcode<>0
  3153.                 begin
  3154.                     raiserror(21369, 16, -1, @publication)    
  3155.                     goto UNDO
  3156.                 end
  3157.                 update syspublications set ad_guidname=NULL where pubid=@pubid
  3158.                 if @@ERROR<>0
  3159.                 begin
  3160.                     raiserror(21369, 16, -1, @publication)    
  3161.                     goto UNDO
  3162.                 end
  3163.                END
  3164.        END
  3165.  
  3166.     IF LOWER(@property) = 'taskid'
  3167.        BEGIN
  3168.             -- No longer supported
  3169.             RAISERROR (21023, 16, -1,'@taskid')
  3170.             goto UNDO
  3171.        END
  3172.  
  3173.     IF LOWER(@property) = 'sync_method'
  3174.         BEGIN
  3175.  
  3176.             /*
  3177.             ** Check for a valid synchronization method.
  3178.             */
  3179.  
  3180.             IF LOWER(@value) NOT IN ('native', 'character', 'bcp native', 'bcp character', 'concurrent', 'concurrent_c')
  3181.                 BEGIN
  3182.                     RAISERROR (14014, 16, -1)
  3183.                     GOTO UNDO
  3184.                 END
  3185.  
  3186.             /*
  3187.             ** Determine the integer value for the sync_method.
  3188.             */
  3189.  
  3190.             IF LOWER(@value) IN ('native', 'bcp native')
  3191.                 SELECT @syncmethodid = 0
  3192.             ELSE IF LOWER(@value) IN ('character', 'bcp character')
  3193.                 SELECT @syncmethodid = 1
  3194.             ELSE IF LOWER(@value) IN ( 'concurrent' )
  3195.                 SELECT @syncmethodid = 3
  3196.             ELSE IF LOWER(@value) IN ( 'concurrent_c' )
  3197.                 SELECT @syncmethodid = 4
  3198.  
  3199.             if @syncmethodid NOT IN (1,4) and @allow_dts = 1
  3200.             begin
  3201.                 raiserror(21172, 16, -1)
  3202.                 GOTO UNDO
  3203.             end
  3204.  
  3205.             -- Non sql subscribers can only use char bcp (not concurrent)
  3206.             if @syncmethodid <> 1
  3207.             begin
  3208.                 IF EXISTS( select * from syspublications sp, syssubscriptions ss, 
  3209.                             sysarticles sa, master..sysservers srv
  3210.                            where sp.pubid = @pubid 
  3211.                            and sp.pubid = sa.pubid
  3212.                            and sa.artid = ss.artid
  3213.                            and srv.srvid = ss.srvid
  3214.                            and srv.srvproduct = N'MSREPL-NONSQL' collate database_default)
  3215.                 BEGIN
  3216.                     RAISERROR(20593, 16, -1, @publication )
  3217.                     GOTO UNDO
  3218.                 END             
  3219.             end
  3220.  
  3221.             if exists (select * from syspublications where
  3222.                 pubid = @pubid and
  3223.                 sync_method <> @syncmethodid)
  3224.             begin
  3225.                 /*
  3226.                 ** Update the publication with the new synchronization method.
  3227.                 */
  3228.  
  3229.                 /*
  3230.                 ** If we switch to character mode bcp (an indication that this 
  3231.                 ** publication may support non-SQL Server subscribers) for this 
  3232.                 ** publication, the pre/post snapshot commands settings should be
  3233.                 ** nullified  
  3234.                 */    
  3235.                 IF @syncmethodid = 1
  3236.                 BEGIN
  3237.  
  3238.                     UPDATE syspublications 
  3239.                     SET sync_method = @syncmethodid, pre_snapshot_script = NULL,
  3240.                         post_snapshot_script = NULL
  3241.                     WHERE pubid = @pubid
  3242.  
  3243.                 END    
  3244.                 ELSE
  3245.                 BEGIN
  3246.                     UPDATE syspublications
  3247.                        SET sync_method = @syncmethodid
  3248.                      WHERE pubid = @pubid
  3249.                 END
  3250.  
  3251.                 IF @@ERROR <> 0 GOTO UNDO
  3252.             end            
  3253.         END
  3254.  
  3255.     IF LOWER(@property) = 'status'
  3256.         BEGIN
  3257.             
  3258.             /*
  3259.             ** Check to make sure that we have a valid status.
  3260.             */
  3261.  
  3262.             IF LOWER(@value) NOT IN ('active', 'inactive')
  3263.                 BEGIN
  3264.                     RAISERROR (14012, 16, -1)
  3265.                     GOTO UNDO
  3266.                 END
  3267.  
  3268.             /*
  3269.             ** Determine the integer value for the status.
  3270.             */
  3271.  
  3272.             IF LOWER(@value) = 'active'
  3273.                 SELECT @statusid = 1
  3274.             ELSE
  3275.                 SELECT @statusid = 0
  3276.  
  3277.             /* If status changed */
  3278.             IF EXISTS (SELECT * FROM syspublications
  3279.                 WHERE  pubid = @pubid  AND
  3280.                  status <> @statusid)
  3281.             BEGIN
  3282.     
  3283.                 /* 
  3284.                 ** If change the status of the publication,
  3285.                 ** virtual anonymous subscription have to be recreated.
  3286.                 **
  3287.                 */
  3288.                 IF @allow_anonymous = 1
  3289.                 BEGIN
  3290.                     /* Drop virtual subscriptions */
  3291.                     EXEC @retcode = dbo.sp_dropsubscription 
  3292.                         @publication = @publication, 
  3293.                         @article = 'all', 
  3294.                         @subscriber = NULL,
  3295.                         @reserved = 'internal'
  3296.                     IF @@ERROR <> 0 OR @retcode <> 0
  3297.                     BEGIN
  3298.                         GOTO UNDO
  3299.                     END
  3300.                 END
  3301.  
  3302.                 /*
  3303.                 ** Update the publication with the new status.
  3304.                 */
  3305.  
  3306.                 UPDATE syspublications
  3307.                    SET status = @statusid
  3308.                  WHERE pubid = @pubid
  3309.  
  3310.                 IF @@ERROR <> 0 
  3311.                 BEGIN
  3312.                     GOTO UNDO                
  3313.                 END
  3314.                 
  3315.                 IF @allow_anonymous = 1
  3316.                     SELECT @add_virtual_back = 1
  3317.             END
  3318.         END
  3319.  
  3320.     IF LOWER(@property) = 'repl_freq'
  3321.         BEGIN
  3322.  
  3323.             /*
  3324.             ** Check for a valid replication frequency value.
  3325.             */
  3326.  
  3327.             IF LOWER(@value) NOT IN ('continuous', 'snapshot')
  3328.                 BEGIN
  3329.                     RAISERROR (14015, 16, -1)
  3330.                     GOTO UNDO
  3331.                 END
  3332.  
  3333.  
  3334.             /*
  3335.             ** Determine the integer value for the replication frequency.
  3336.             */
  3337.  
  3338.             IF LOWER(@value) = 'continuous'
  3339.                 SELECT @replfreqid = 0
  3340.             ELSE
  3341.                 SELECT @replfreqid = 1
  3342.  
  3343.             /*
  3344.             ** Only unsubscribed publications may have this modified.
  3345.             */
  3346.             IF EXISTS (SELECT * FROM syssubscriptions s
  3347.                        INNER JOIN sysextendedarticlesview a on s.artid = a.artid
  3348.                         WHERE s.status <> @subscribed
  3349.                           AND s.srvid >= 0 
  3350.                           AND a.pubid = @pubid)
  3351.             BEGIN
  3352.                 RAISERROR (14033, 11, -1)
  3353.                 GOTO UNDO
  3354.             END
  3355.  
  3356.  
  3357.  
  3358. /*
  3359.  
  3360.             IF EXISTS (SELECT * FROM syssubscriptions
  3361.             WHERE 
  3362.                 status <> @subscribed AND
  3363.                 srvid >= 0 AND
  3364.                 artid IN (SELECT artid FROM sysextendedarticlesview where pubid
  3365.                = @pubid))
  3366.             BEGIN
  3367.                 RAISERROR (14033, 11, -1)
  3368.                 GOTO UNDO
  3369.             END
  3370.  
  3371. */
  3372.             IF @immediate_sync = 1
  3373.             BEGIN
  3374.                 /* Drop virtual subscriptions */
  3375.                 EXEC @retcode = dbo.sp_dropsubscription 
  3376.                     @publication = @publication, 
  3377.                     @article = 'all', 
  3378.                     @subscriber = NULL,
  3379.                     @reserved = 'internal'
  3380.                 IF @@ERROR <> 0 OR @retcode <> 0
  3381.                 BEGIN
  3382.                     GOTO UNDO                
  3383.                 END
  3384.             END
  3385.             /*
  3386.             ** Update the publication with the new replication frequency.
  3387.             */
  3388.  
  3389.             UPDATE syspublications
  3390.                SET repl_freq = @replfreqid
  3391.              WHERE pubid = @pubid
  3392.  
  3393.             IF @@ERROR <> 0 
  3394.             BEGIN
  3395.                 GOTO UNDO
  3396.             END
  3397.  
  3398.             IF @immediate_sync = 1
  3399.                 SELECT @add_virtual_back = 1
  3400.         END
  3401.  
  3402.     IF LOWER(@property) = N'alt_snapshot_folder'
  3403.         BEGIN
  3404.             -- If the alt_snapshot_folder is set to '' or NULL,
  3405.             -- set the compress_snapshot bit to 0 and disable
  3406.             -- internet support  
  3407.             IF @value IS NULL OR @value = N''
  3408.             BEGIN
  3409.                 UPDATE syspublications
  3410.                    SET alt_snapshot_folder = @value,
  3411.                        compress_snapshot = 0,
  3412.                        enabled_for_internet = 0
  3413.                  WHERE pubid = @pubid
  3414.             END
  3415.             ELSE
  3416.             BEGIN
  3417.                 UPDATE syspublications
  3418.                    SET alt_snapshot_folder = @value
  3419.                  WHERE pubid = @pubid
  3420.  
  3421.             END
  3422.             IF @@error <> 0
  3423.             BEGIN
  3424.                GOTO UNDO
  3425.             END
  3426.  
  3427.         END
  3428.  
  3429.     IF LOWER(@property) = N'pre_snapshot_script'
  3430.         BEGIN
  3431.             UPDATE syspublications
  3432.                SET pre_snapshot_script = @value
  3433.              WHERE pubid = @pubid
  3434.             IF @@error <> 0
  3435.             BEGIN
  3436.                GOTO UNDO
  3437.             END
  3438.         END
  3439.  
  3440.     IF LOWER(@property) = N'post_snapshot_script'
  3441.         BEGIN
  3442.             UPDATE syspublications
  3443.                SET post_snapshot_script = @value
  3444.              WHERE pubid = @pubid
  3445.             IF @@error <> 0
  3446.             BEGIN
  3447.                GOTO UNDO
  3448.             END
  3449.         END
  3450.  
  3451.     IF LOWER(@property) = N'ftp_address'
  3452.         BEGIN
  3453.     
  3454.             IF @value IS NULL OR @value = N''
  3455.             BEGIN
  3456.                 UPDATE syspublications
  3457.                    SET ftp_address = @value,
  3458.                        enabled_for_internet = 0
  3459.                  WHERE pubid = @pubid
  3460.                 IF @@error <> 0
  3461.                 BEGIN
  3462.                     GOTO UNDO
  3463.                 END
  3464.             END
  3465.             ELSE
  3466.             BEGIN
  3467.                 UPDATE syspublications
  3468.                    SET ftp_address = @value
  3469.                  WHERE pubid = @pubid
  3470.                 IF @@error <> 0
  3471.                 BEGIN
  3472.                     GOTO UNDO
  3473.                 END
  3474.             END
  3475.         END
  3476.             
  3477.     IF LOWER(@property) = N'ftp_port'
  3478.         BEGIN
  3479.             UPDATE syspublications
  3480.                SET ftp_port = CONVERT(int, @value)
  3481.              WHERE pubid = @pubid
  3482.             IF @@error <> 0
  3483.             BEGIN
  3484.                GOTO UNDO
  3485.             END
  3486.         END
  3487.  
  3488.     IF LOWER(@property) = N'ftp_subdirectory'
  3489.         BEGIN
  3490.             UPDATE syspublications
  3491.                SET ftp_subdirectory = @value
  3492.              WHERE pubid = @pubid
  3493.             IF @@error <> 0
  3494.             BEGIN
  3495.                GOTO UNDO
  3496.             END
  3497.         END
  3498.  
  3499.     IF LOWER(@property) = N'ftp_login'
  3500.         BEGIN
  3501.             UPDATE syspublications
  3502.                SET ftp_login = @value
  3503.              WHERE pubid = @pubid
  3504.             IF @@error <> 0
  3505.             BEGIN
  3506.                GOTO UNDO
  3507.             END
  3508.         END
  3509.  
  3510.     IF LOWER(@property) = N'ftp_password'
  3511.         BEGIN
  3512.             SELECT @enc_ftp_password = NULL
  3513.             IF @value IS NOT NULL
  3514.             BEGIN
  3515.                 SELECT @enc_ftp_password = @value
  3516.                 EXEC @retcode = master.dbo.xp_repl_encrypt @enc_ftp_password OUTPUT
  3517.                 IF @retcode <> 0
  3518.                 BEGIN
  3519.                     GOTO UNDO
  3520.                 END
  3521.             END
  3522.             UPDATE syspublications
  3523.                SET ftp_password = @enc_ftp_password
  3524.              WHERE pubid = @pubid
  3525.             IF @@error <> 0
  3526.             BEGIN
  3527.                GOTO UNDO
  3528.             END
  3529.         END
  3530.  
  3531.     IF LOWER(@property) IN ('independent_agent', 'immediate_sync','enabled_for_internet',
  3532.             'allow_push', 'allow_pull', 'allow_anonymous', 'snapshot_in_defaultfolder', 
  3533.             'compress_snapshot', 'allow_subscription_copy')
  3534.     BEGIN
  3535.  
  3536.     
  3537.         /*
  3538.         ** Check for a valid  value.
  3539.         */
  3540.  
  3541.         IF LOWER(@value) NOT IN ('true', 'false')
  3542.         BEGIN
  3543.             RAISERROR (14137, 16, -1)
  3544.             GOTO UNDO
  3545.         END
  3546.  
  3547.         /*
  3548.         ** set value bit
  3549.         */
  3550.         IF LOWER(@value) = 'true'
  3551.             SELECT @value_bit = 1
  3552.         ELSE 
  3553.             SELECT @value_bit = 0
  3554.  
  3555.  
  3556.         IF LOWER(@property) = 'independent_agent'
  3557.         BEGIN
  3558.             SELECT @prev_value_bit = independent_agent
  3559.             FROM syspublications 
  3560.             WHERE name = @publication
  3561.  
  3562.             IF @prev_value_bit <> @value_bit
  3563.             BEGIN
  3564.  
  3565.                 IF @immediate_sync = 1 AND @value_bit = 0
  3566.                 BEGIN
  3567.                     RAISERROR (21022, 16, -1)
  3568.                     GOTO UNDO
  3569.                 END    
  3570.  
  3571.             /* 
  3572.             ** no subscriptions are allowed
  3573.             */
  3574.             IF EXISTS (SELECT * FROM syssubscriptions ss, sysextendedarticlesview sa
  3575.                     WHERE ss.artid = sa.artid
  3576.                         AND   sa.pubid = @pubid
  3577.                         AND   ss.srvid <> @virtual_id )
  3578.             BEGIN
  3579.                 RAISERROR (20013, 16, -1, @property)
  3580.                 GOTO UNDO
  3581.             END
  3582.  
  3583.             --
  3584.             -- No share agents for DTS/Updating publications
  3585.             --
  3586.             if (@value_bit = 0 and 
  3587.                 (@allow_dts = 1 or @allow_sync_tran = 1 or @allow_queued_tran = 1))            
  3588.             begin
  3589.                 raiserror(21173, 16, -1)
  3590.                 return(1)
  3591.             end
  3592.  
  3593.             /* Update the publication type */
  3594.             UPDATE syspublications 
  3595.             SET independent_agent = @value_bit
  3596.             WHERE pubid = @pubid
  3597.             IF @@error <> 0
  3598.             BEGIN
  3599.             GOTO UNDO
  3600.             END
  3601.             END
  3602.         END
  3603.  
  3604.         IF LOWER(@property) = 'immediate_sync'
  3605.         BEGIN
  3606.  
  3607.  
  3608.             SELECT @prev_value_bit = immediate_sync
  3609.               FROM syspublications 
  3610.              WHERE name = @publication
  3611.  
  3612.             IF @prev_value_bit <> @value_bit
  3613.             BEGIN
  3614.  
  3615.                IF @independent_agent = 0 AND @value_bit = 1
  3616.                BEGIN
  3617.                     RAISERROR (21022, 16, -1)
  3618.                     GOTO UNDO
  3619.                END    
  3620.  
  3621.                /* 
  3622.                ** The publication has to be immediate_sync type to
  3623.                ** allow anonymous subscriptions
  3624.                */
  3625.                 IF @value_bit = 0 AND
  3626.                     EXISTS (SELECT * FROM syspublications
  3627.                         WHERE pubid = @pubid
  3628.                         AND   allow_anonymous = 1 )
  3629.                 BEGIN
  3630.                     RAISERROR (20011, 16, -1, @property)
  3631.                     GOTO UNDO
  3632.                 END
  3633.  
  3634.             
  3635.                 /* 
  3636.                 ** If turn on immediate_sync, we need to add virtual subscriptions,
  3637.                 ** Otherwise, we need to drop them
  3638.                 ** When adding, we need to change publication bit first
  3639.                 ** When dropping, we need to change publication bit second
  3640.                 */
  3641.                 IF @value_bit = 0
  3642.                 BEGIN
  3643.                     -- Drop virtual subscriptions 
  3644.                     EXEC @retcode = dbo.sp_dropsubscription 
  3645.                         @publication = @publication, 
  3646.                         @article = 'all', 
  3647.                         @subscriber = NULL,
  3648.                         @reserved = 'internal'
  3649.                     IF @@ERROR <> 0 OR @retcode <> 0
  3650.                     BEGIN
  3651.                         GOTO UNDO
  3652.                     END
  3653.  
  3654.                     -- Reset the immediate_sync ready bit
  3655.                     UPDATE syspublications 
  3656.                         SET immediate_sync_ready = 0
  3657.                         WHERE pubid = @pubid
  3658.  
  3659.                 END
  3660.  
  3661.                 /* Update the publication type */
  3662.                 UPDATE syspublications 
  3663.                     SET immediate_sync = @value_bit
  3664.                     WHERE pubid = @pubid
  3665.                 IF @@error <> 0
  3666.                 BEGIN
  3667.                     GOTO UNDO
  3668.                 END
  3669.  
  3670.  
  3671.                 IF @value_bit = 1
  3672.                     SELECT @add_virtual_back = 1
  3673.             END
  3674.         END
  3675.  
  3676.         IF LOWER(@property) = 'allow_anonymous'
  3677.         BEGIN
  3678.  
  3679.             SELECT @prev_value_bit = allow_anonymous
  3680.               FROM syspublications 
  3681.              WHERE name = @publication
  3682.  
  3683.             IF @prev_value_bit <> @value_bit
  3684.             BEGIN
  3685.                 /* 
  3686.                 ** The publication has to be immediate_sync type to
  3687.                 ** allow anonymous subscriptions
  3688.                 */
  3689.                 IF @value_bit = 1 AND
  3690.                     NOT EXISTS (SELECT * FROM syspublications
  3691.                         WHERE pubid = @pubid
  3692.                         AND   immediate_sync = 1 )
  3693.                 BEGIN
  3694.                     RAISERROR (20011, 16, -1, @property)
  3695.                     GOTO UNDO
  3696.                 END
  3697.                 
  3698.                 
  3699.  
  3700.                 /* Drop virtual subscriptions */
  3701.                 EXEC @retcode = dbo.sp_dropsubscription 
  3702.                     @publication = @publication, 
  3703.                     @article = 'all', 
  3704.                     @subscriber = NULL,
  3705.                     @reserved = 'internal'
  3706.                 IF @@ERROR <> 0 OR @retcode <> 0
  3707.                 BEGIN
  3708.                     GOTO UNDO
  3709.                 END
  3710.  
  3711.                 /* Update the publication type */
  3712.                 UPDATE syspublications 
  3713.                     SET allow_anonymous = @value_bit
  3714.                     WHERE pubid = @pubid
  3715.                 IF @@error <> 0
  3716.                 BEGIN
  3717.                    GOTO UNDO
  3718.                 END
  3719.  
  3720.                 /* 
  3721.                 ** add virtual subscriptions back again to enable 
  3722.                 ** anonymous subscription.
  3723.                 */
  3724.                 SELECT @add_virtual_back = 1
  3725.  
  3726.             END
  3727.  
  3728.         END
  3729.  
  3730.         IF LOWER(@property) = 'enabled_for_internet'
  3731.         BEGIN
  3732.  
  3733.             UPDATE syspublications 
  3734.                SET enabled_for_internet = @value_bit
  3735.              WHERE pubid = @pubid
  3736.  
  3737.             IF @@error <> 0
  3738.             BEGIN
  3739.                GOTO UNDO
  3740.             END
  3741.         END
  3742.  
  3743.         IF LOWER(@property) = 'allow_push'
  3744.         BEGIN
  3745.  
  3746.            /* 
  3747.            ** If turn it off, make sure there's no push subscriptions left
  3748.            */
  3749.            IF @value_bit = 0 AND
  3750.             EXISTS (SELECT * FROM syssubscriptions ss, sysextendedarticlesview sa
  3751.                     WHERE ss.artid = sa.artid
  3752.                     AND   sa.pubid = @pubid
  3753.                     AND      ss.subscription_type = @push
  3754.                     AND   ss.srvid <> @virtual_id )
  3755.             BEGIN
  3756.                 RAISERROR (20012, 16, -1)
  3757.                 GOTO UNDO
  3758.             END
  3759.  
  3760.             
  3761.             /* Update the publication type */
  3762.             UPDATE syspublications 
  3763.                 SET allow_push = @value_bit
  3764.                 WHERE pubid = @pubid
  3765.             IF @@error <> 0
  3766.             BEGIN
  3767.                GOTO UNDO
  3768.             END
  3769.         END
  3770.  
  3771.         IF LOWER(@property) = 'allow_pull'
  3772.         BEGIN
  3773.            /* 
  3774.            ** If turn it off, make sure there's no pull subscriptions left
  3775.            */
  3776.            IF @value_bit = 0 AND
  3777.             EXISTS (SELECT * FROM syssubscriptions ss, sysextendedarticlesview sa
  3778.                     WHERE ss.artid = sa.artid
  3779.                     AND   sa.pubid = @pubid
  3780.                     AND      ss.subscription_type = @pull
  3781.                     AND   ss.srvid <> @virtual_id )
  3782.             BEGIN
  3783.                 RAISERROR (20013, 16, -1, @property)
  3784.                 GOTO UNDO
  3785.             END
  3786.             /* Update the publication type */
  3787.             UPDATE syspublications 
  3788.                 SET allow_pull = @value_bit
  3789.                 WHERE pubid = @pubid
  3790.             IF @@error <> 0
  3791.             BEGIN
  3792.                GOTO UNDO
  3793.             END
  3794.         END
  3795.  
  3796.         IF LOWER(@property) = 'snapshot_in_defaultfolder'
  3797.         BEGIN
  3798.             -- snapshot_in_defaultfolder = 1 is only meaningful when
  3799.             -- alt_snapshot_folder is non-null, otherwise 
  3800.             -- a copy of the snapshot files is always kept
  3801.             -- at the publisher's working directory 
  3802.     
  3803.             UPDATE syspublications 
  3804.                SET snapshot_in_defaultfolder = @value_bit
  3805.              WHERE pubid = @pubid
  3806.             IF @@error <> 0
  3807.             BEGIN
  3808.                 GOTO UNDO
  3809.             END
  3810.         END
  3811.  
  3812.         IF LOWER(@property) = 'compress_snapshot'
  3813.         BEGIN
  3814.  
  3815.             UPDATE syspublications
  3816.                SET compress_snapshot = @value_bit
  3817.              WHERE pubid = @pubid
  3818.             IF @@error <> 0
  3819.             BEGIN
  3820.                 GOTO UNDO
  3821.             END
  3822.         END
  3823.  
  3824.         IF LOWER(@property) = 'allow_subscription_copy'
  3825.         BEGIN
  3826.             if @value_bit = 1 and @immediate_sync = 0
  3827.             begin
  3828.                 raiserror(21210, 16, -1)
  3829.                 goto UNDO
  3830.             end
  3831.  
  3832.             UPDATE syspublications
  3833.                SET allow_subscription_copy = @value_bit
  3834.              WHERE pubid = @pubid
  3835.             IF @@error <> 0
  3836.             BEGIN
  3837.                 GOTO UNDO
  3838.             END
  3839.         END
  3840.     END
  3841.  
  3842.     /* Update publication property at the distributor side if necessary */
  3843.     IF LOWER(@property) IN ('description', 'repl_freq', 'independent_agent',
  3844.         'immediate_sync', 'allow_push',
  3845.         'allow_pull', 'allow_anonymous','retention', 'allow_subscription_copy')
  3846.     BEGIN
  3847.         /* Translate the property names and values  */
  3848.         IF LOWER(@property) = 'repl_freq'
  3849.         BEGIN
  3850.             SELECT @property = 'publication_type'
  3851.             SELECT @value = STR(@replfreqid)
  3852.         END
  3853.  
  3854.         /* Translate values */
  3855.         IF LOWER(@value) = 'true'
  3856.             SELECT @value = '1'
  3857.         ELSE IF LOWER(@value) = 'false'
  3858.             SELECT @value = '0'
  3859.  
  3860.         /*
  3861.         ** Get distribution server information for remote RPC call.
  3862.         */
  3863.         EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  3864.            @distribdb   = @distribdb OUTPUT
  3865.         IF @@ERROR <> 0 or @retcode <> 0
  3866.             BEGIN
  3867.                 GOTO UNDO
  3868.             END
  3869.  
  3870.         SELECT @dbname =  DB_NAME()
  3871.         
  3872.         SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  3873.             '.dbo.sp_MSchange_publication'
  3874.     
  3875.         EXECUTE @retcode = @distproc
  3876.             @publisher = @@SERVERNAME,
  3877.             @publisher_db = @dbname,
  3878.             @publication = @publication,
  3879.             @property = @property,
  3880.             @value = @value
  3881.  
  3882.         IF @@ERROR <> 0 OR @retcode <> 0
  3883.         BEGIN
  3884.             GOTO UNDO
  3885.         END
  3886.     END
  3887.     
  3888.     IF @add_virtual_back = 1    
  3889.     BEGIN
  3890.         /* Add virtual subscriptions back*/
  3891.         EXEC @retcode = dbo.sp_addsubscription 
  3892.             @publication = @publication, 
  3893.             @article = 'all',
  3894.             @subscriber = NULL,
  3895.             @destination_db = 'virtual',
  3896.             @sync_type = 'automatic',
  3897.             @status = NULL, 
  3898.             @reserved = 'internal'
  3899.         IF @@ERROR <> 0 OR @retcode <> 0
  3900.         BEGIN
  3901.             GOTO UNDO                    
  3902.         END
  3903.     END
  3904.  
  3905.     --
  3906.     -- Queued properties
  3907.     --
  3908.     IF (LOWER(@property) IN ('conflict_policy', 'centralized_conflicts', 'conflict_retention', 'queue_type'))
  3909.     BEGIN
  3910.         --
  3911.         -- we will consider changes only if the publication supports queued operations
  3912.         --
  3913.         if exists (select * from syspublications 
  3914.                 where pubid = @pubid and allow_queued_tran = 1)
  3915.         BEGIN
  3916.             IF (LOWER(@property) = 'conflict_policy')
  3917.             BEGIN
  3918.                 if (LOWER(@value) = 'sub reinit')
  3919.                     select @conflict_policy_id = 3
  3920.                 else if (LOWER(@value) = 'pub wins')
  3921.                     select @conflict_policy_id = 1
  3922.                 else if (LOWER(@value) = 'sub wins')
  3923.                     select @conflict_policy_id = 2
  3924.                 else
  3925.                 BEGIN
  3926.                     raiserror (21184, 16, 3, 'conflict_policy', 'sub reinit', 'pub wins', 'sub wins')
  3927.                     GOTO UNDO                    
  3928.                 END
  3929.  
  3930.                 --
  3931.                 -- cannot change this parameter once we have subscriptions
  3932.                 --
  3933.                 IF EXISTS (SELECT * FROM syssubscriptions ss, sysextendedarticlesview sa
  3934.                                 WHERE ss.artid = sa.artid
  3935.                                 AND   sa.pubid = @pubid)
  3936.                 BEGIN
  3937.                     RAISERROR (21268, 16, 1)
  3938.                     GOTO UNDO
  3939.                 END
  3940.  
  3941.                 --
  3942.                 -- Check snapshot permissible values
  3943.                 --
  3944.                 if ((@replfreqid = 1) and (@conflict_policy_id = 1))
  3945.                 begin
  3946.                     raiserror (21270, 16, 1, '@conflict_policy', @value)
  3947.                     GOTO UNDO                    
  3948.                 end
  3949.                 
  3950.                 UPDATE syspublications
  3951.                 SET conflict_policy = @conflict_policy_id
  3952.                 WHERE pubid = @pubid
  3953.                 IF @@error <> 0
  3954.                 BEGIN
  3955.                     GOTO UNDO
  3956.                 END
  3957.             END
  3958.  
  3959.             IF (LOWER(@property) = 'centralized_conflicts')
  3960.             BEGIN
  3961.                 if (LOWER(@value) = 'true')
  3962.                     select @centralized_conflicts_bit = 1
  3963.                 else if (LOWER(@value) = 'false')
  3964.                     select @centralized_conflicts_bit = 0
  3965.                 else
  3966.                 begin
  3967.                     raiserror (14148, 16, 3, 'centralized_conflicts')
  3968.                     GOTO UNDO                    
  3969.                 end
  3970.  
  3971.                 --
  3972.                 -- Check snapshot permissible values
  3973.                 --
  3974.                 if ((@replfreqid = 1) and (@centralized_conflicts_bit = 0))
  3975.                 begin
  3976.                     raiserror (21270, 16, 1, '@centralized_conflicts', @value)
  3977.                     GOTO UNDO                    
  3978.                 end
  3979.  
  3980.                 --
  3981.                 -- cannot change this parameter once we have subscriptions
  3982.                 --
  3983.                 IF EXISTS (SELECT * FROM syssubscriptions ss, sysextendedarticlesview sa
  3984.                                 WHERE ss.artid = sa.artid
  3985.                                 AND   sa.pubid = @pubid)
  3986.                 BEGIN
  3987.                     RAISERROR (21268, 16, 2)
  3988.                     GOTO UNDO
  3989.                 END
  3990.  
  3991.                 UPDATE syspublications
  3992.                 SET centralized_conflicts = @centralized_conflicts_bit
  3993.                 WHERE pubid = @pubid
  3994.                 IF @@error <> 0
  3995.                 BEGIN
  3996.                     GOTO UNDO
  3997.                 END
  3998.             END
  3999.  
  4000.             IF (LOWER(@property) = 'conflict_retention')
  4001.             BEGIN
  4002.                 select @conflict_retention = CAST(@value as integer)
  4003.                 if (@@error != 0) or (@conflict_retention < 0)
  4004.                 BEGIN
  4005.                     raiserror(20050, 16, -1, 0)
  4006.                     GOTO UNDO                    
  4007.                 END
  4008.                 if (@conflict_retention IS NULL)
  4009.                     select @conflict_retention = 60
  4010.  
  4011.                 UPDATE syspublications
  4012.                 SET conflict_retention = @conflict_retention
  4013.                 WHERE pubid = @pubid
  4014.                 IF @@error <> 0
  4015.                 BEGIN
  4016.                     GOTO UNDO
  4017.                 END
  4018.             END
  4019.             
  4020.             IF (LOWER(@property) = 'queue_type')
  4021.             BEGIN                
  4022.                 IF (CAST(@value as integer) NOT IN (1,2))
  4023.                 BEGIN
  4024.                     RAISERROR(21267, 16, 1, '1,2')
  4025.                     GOTO UNDO
  4026.                 end
  4027.  
  4028.                 IF (CAST(@value as integer) != @queue_type)
  4029.                 BEGIN
  4030.                     select @queue_type = CAST(@value as integer)
  4031.                     IF EXISTS (SELECT * FROM syssubscriptions ss, sysextendedarticlesview sa
  4032.                                     WHERE ss.artid = sa.artid
  4033.                                     AND   sa.pubid = @pubid)
  4034.                     BEGIN
  4035.                         RAISERROR (21268, 16, 3)
  4036.                         GOTO UNDO
  4037.                     END
  4038.  
  4039.                     UPDATE syspublications
  4040.                     SET queue_type = @queue_type
  4041.                     WHERE pubid = @pubid
  4042.                     IF @@error <> 0
  4043.                     BEGIN
  4044.                         GOTO UNDO
  4045.                     END
  4046.  
  4047.                     --
  4048.                     -- For MSMQ queue_type - Check if the distributor supports it
  4049.                     --
  4050.                     if (@queue_type = 1)
  4051.                     begin
  4052.                         EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  4053.                                                 @distribdb   = @distribdb OUTPUT
  4054.                         IF @@ERROR <> 0 or @retcode <> 0
  4055.                         BEGIN
  4056.                             GOTO UNDO
  4057.                         END
  4058.  
  4059.                         SELECT @dbname =  DB_NAME()
  4060.                                 ,@distproc = RTRIM(@distributor) + '.' + @distribdb + 
  4061.                                             N'.dbo.sp_MSchange_publication'
  4062.  
  4063.                         EXECUTE @retcode = @distproc
  4064.                                         @publisher = @@SERVERNAME,
  4065.                                         @publisher_db = @dbname,
  4066.                                         @publication = @publication,
  4067.                                         @property = @property,
  4068.                                         @value = @value
  4069.  
  4070.                         IF @@ERROR <> 0 OR @retcode <> 0
  4071.                         BEGIN
  4072.                             GOTO UNDO
  4073.                         END
  4074.                     end
  4075.                 END
  4076.             END            
  4077.         END
  4078.     END
  4079.  
  4080.     
  4081.     -- Have to call this stored procedure to invalidate existing snapshot or reint
  4082.     -- subscriptions if needed
  4083.     EXECUTE @retcode  = dbo.sp_MSreinit_article
  4084.         @publication = @publication, 
  4085.         @need_new_snapshot = @need_new_snapshot,
  4086.         @need_reinit_subscription = @need_reinit_subscription
  4087.         ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  4088.         ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  4089.     IF @@ERROR <> 0 OR @retcode <> 0
  4090.         GOTO UNDO
  4091.  
  4092.     COMMIT TRAN sp_changepublication
  4093.  
  4094.     --update its registration in active directory
  4095.     if @in_ActiveD=1 and LOWER(@property) IN ('description','allow_pull', 'allow_anonymous')
  4096.     begin
  4097.         create table #guid_name_for_ADupdate(ad_guidname sysname collate database_default null)
  4098.         if @@ERROR<>0
  4099.         begin
  4100.             goto FAILURE
  4101.         end
  4102.         insert into #guid_name_for_ADupdate exec @retcode = master.dbo.sp_ActiveDirectory_Obj N'UPDATE', N'PUBLICATION', @publication, @db_name, @ad_guidname
  4103.         if @@ERROR<>0 or @retcode<>0
  4104.         begin
  4105.             goto FAILURE                     
  4106.            end
  4107.         select TOP 1 @ad_guidname = ad_guidname from #guid_name_for_ADupdate
  4108.         if @ad_guidname is not NULL
  4109.         begin
  4110.             update syspublications set ad_guidname=@ad_guidname where pubid=@pubid
  4111.             if @@ERROR<>0
  4112.                 goto FAILURE
  4113.         end
  4114.         drop table #guid_name_for_ADupdate
  4115.     end
  4116.  
  4117.     /*
  4118.     ** Return succeed.
  4119.     */
  4120.  
  4121.     RAISERROR (14077, 10, -1)
  4122.     RETURN (0)
  4123. FAILURE:
  4124.     drop table #guid_name_for_ADupdate
  4125.     raiserror(21371, 10, -1, @publication)
  4126.     return (1)   
  4127.  
  4128. UNDO:
  4129.     IF @@TRANCOUNT > 0
  4130.     begin 
  4131.         ROLLBACK TRAN sp_changepublication
  4132.         COMMIT TRAN
  4133.     end
  4134. END
  4135. GO
  4136.  
  4137. EXEC dbo.sp_MS_marksystemobject sp_changepublication
  4138. GO
  4139.  
  4140. print ''
  4141. print 'Creating procedure sp_changesubscription'
  4142. GO
  4143. /* This function should be disallowed */
  4144. CREATE PROCEDURE sp_changesubscription (
  4145.     @publication sysname = NULL,        /* Publication name */
  4146.     @article sysname = NULL,            /* Article name */
  4147.     @subscriber sysname,              /* Subscriber name */
  4148.     @property nvarchar(15) = NULL,           /* The property to change */
  4149.     @value nvarchar(255) = NULL              /* The new property value */
  4150.     ) AS
  4151.  
  4152.     SET NOCOUNT ON
  4153.     RAISERROR (21023, 16, -1,'sp_changesubscription')
  4154.     RETURN(1)
  4155. go
  4156.  
  4157. dump tran master with no_log
  4158. go
  4159.  
  4160. EXEC dbo.sp_MS_marksystemobject sp_changesubscription
  4161. GO
  4162.  
  4163.  
  4164. print ''
  4165. print 'Creating procedure sp_helparticle'
  4166. go
  4167.  
  4168. CREATE PROCEDURE sp_helparticle (
  4169.     @publication sysname,         /* The publication name */
  4170.     @article sysname = '%',       /* The article name */
  4171.     @returnfilter bit = 1         /* Return filter flag */
  4172.     ) AS
  4173.  
  4174.     SET NOCOUNT ON
  4175.  
  4176.     /*
  4177.     ** Declarations.
  4178.     */
  4179.  
  4180.     DECLARE @pubid int
  4181.     DECLARE @retcode int
  4182.     DECLARE @subscriber_bit smallint
  4183.     DECLARE @publish_bit int
  4184.     DECLARE @source_object  sysname
  4185.     DECLARE @source_owner   sysname
  4186.     
  4187.     SELECT @publish_bit = 1
  4188.  
  4189.     /*
  4190.     ** Security Check. To public.
  4191.     
  4192.     */
  4193.     /*
  4194.     ** Check if the database is published.
  4195.     */
  4196.     IF NOT EXISTS (SELECT * FROM master..sysdatabases
  4197.         WHERE name = db_name() collate database_default
  4198.         AND (category & @publish_bit) = @publish_bit)
  4199.         RETURN(0)
  4200.  
  4201.     /*
  4202.     ** Initializations.
  4203.     */
  4204.  
  4205.     SELECT @subscriber_bit = 4
  4206.  
  4207.     IF @publication IS NOT NULL
  4208.         SELECT @pubid = pubid FROM syspublications WHERE name = @publication
  4209.  
  4210.     /*
  4211.     ** Create a temporary table to hold all information.
  4212.     */
  4213.  
  4214.     CREATE TABLE #tab1 (
  4215.         artid               int             NOT NULL,
  4216.         columns             varbinary(32)   NULL,
  4217.         creation_script     nvarchar(255)   collate database_default null,
  4218.         del_cmd             nvarchar(255)   collate database_default null,
  4219.         description         nvarchar(255)   collate database_default null,
  4220.         dest_table          sysname         collate database_default null,
  4221.         old_filter          int             NULL,
  4222.         ins_cmd             nvarchar(255)   collate database_default null,
  4223.         name                sysname         collate database_default not null,
  4224.         objid               int             NOT NULL,
  4225.         pubid               int             NOT NULL,
  4226.         status              tinyint         NOT NULL,
  4227.         sync_objid          int             NULL,
  4228.         type                smallint        NOT NULL,
  4229.         upd_cmd             nvarchar(255)   collate database_default null,
  4230.         source_table        nvarchar(257)   collate database_default null,      /* converted from objid */
  4231.         filter              nvarchar(257)   collate database_default null,      /* converted from old_filter */
  4232.         sync_object         nvarchar(257)   collate database_default null,      /* converted from sync_objid */
  4233.         vpartition          bit             NULL,      /* computed */
  4234.         pre_creation_cmd    tinyint     NOT NULL,
  4235.         filter_clause       ntext           NULL,
  4236.         schema_option       binary(8)       NULL,
  4237.         dest_owner          sysname         collate database_default null,
  4238.         source_owner        sysname         collate database_default null,   /* these two columns are for 7.0 use only */
  4239.         unqua_source_object sysname         collate database_default null,   /* column source_table stays due to backward compatibility */
  4240.         sync_object_owner   sysname         collate database_default null,
  4241.         unqua_sync_object   sysname         collate database_default null,
  4242.         filter_owner        sysname         collate database_default null,
  4243.         unqua_filter        sysname         collate database_default null
  4244.     )
  4245.  
  4246.     CREATE UNIQUE INDEX idx1 ON #tab1 (name, pubid)
  4247.  
  4248.     /*
  4249.     ** Parameter Check:  @publication.
  4250.     ** Check to make sure that there are some articles
  4251.     ** to display.
  4252.     */
  4253.  
  4254.     IF @publication IS NULL
  4255.         BEGIN
  4256.             RAISERROR (14043, 16, -1, '@publication')
  4257.             RETURN (1)
  4258.         END
  4259.  
  4260.     EXECUTE @retcode = dbo.sp_validname @publication
  4261.  
  4262.     IF @retcode <> 0
  4263.     RETURN (1)
  4264.  
  4265.     IF NOT EXISTS (SELECT * FROM syspublications WHERE name = @publication)
  4266.         BEGIN
  4267.             RAISERROR (20026, 11, -1, @publication)
  4268.             RETURN (1)
  4269.         END
  4270.  
  4271.     /*
  4272.     ** Parameter Check:  @article.
  4273.     ** Check to make sure that the article exists, that it conforms
  4274.     ** to the rules for identifiers, and that it isn't NULL.
  4275.     */
  4276.  
  4277.     IF @article IS NULL
  4278.         BEGIN
  4279.             RAISERROR (14043, 16, -1, '@article')
  4280.             RETURN (1)
  4281.         END
  4282.  
  4283.     IF @article <> '%'
  4284.         BEGIN
  4285.  
  4286.             /*
  4287.             EXECUTE @retcode = dbo.sp_validname @article
  4288.  
  4289.             IF @retcode <> 0
  4290.             RETURN (1)
  4291.             */
  4292.  
  4293.             IF NOT EXISTS (SELECT *
  4294.                              FROM sysextendedarticlesview
  4295.                             WHERE name = @article
  4296.                               AND pubid IN (SELECT pubid
  4297.                                               FROM syspublications
  4298.                                              WHERE name = @publication))
  4299.                 BEGIN
  4300.                     RAISERROR (20027, 11, -1, @article)
  4301.                     RETURN (1)
  4302.                 END
  4303.  
  4304.         END
  4305.  
  4306.         
  4307.     IF @returnfilter = 1
  4308.     BEGIN
  4309.         INSERT INTO #tab1 (artid, columns, creation_script, del_cmd,
  4310.                            description, dest_table, old_filter,
  4311.                            ins_cmd, name, objid, pubid, status,
  4312.                            sync_objid, type, upd_cmd, source_table,
  4313.                            filter, vpartition, pre_creation_cmd,
  4314.                filter_clause, schema_option, dest_owner, source_owner, unqua_source_object, 
  4315.                sync_object_owner, unqua_sync_object, filter_owner, unqua_filter)
  4316.                
  4317.          (SELECT artid, columns, creation_script, del_cmd, a.description,
  4318.                  dest_table, filter, ins_cmd, a.name, objid, a.pubid,
  4319.                  a.status, sync_objid, a.type, upd_cmd, NULL, NULL, 0,
  4320.                 a.pre_creation_cmd, a.filter_clause, a.schema_option, a.dest_owner, 
  4321.                 user_name(o.uid), o.name, 
  4322.                 user_name(sync.uid), sync.name,
  4323.                 user_name(fltr.uid), fltr.name
  4324.             FROM syspublications b, 
  4325.                  sysobjects o, 
  4326.                  sysextendedarticlesview a 
  4327.           LEFT JOIN sysobjects sync on a.sync_objid = sync.id
  4328.           LEFT JOIN sysobjects fltr on a.filter = fltr.id
  4329.            WHERE a.name LIKE @article
  4330.              AND a.objid = o.id
  4331.              AND a.pubid = b.pubid
  4332.              AND b.name = @publication)
  4333.     END
  4334.     ELSE
  4335.     BEGIN
  4336.         INSERT INTO #tab1 (artid, columns, creation_script, del_cmd,
  4337.                            description, dest_table, old_filter,
  4338.                            ins_cmd, name, objid, pubid, status,
  4339.                            sync_objid, type, upd_cmd, source_table,
  4340.                            filter, vpartition, pre_creation_cmd,
  4341.                filter_clause, schema_option, dest_owner, source_owner, unqua_source_object, 
  4342.                sync_object_owner, unqua_sync_object, filter_owner, unqua_filter)
  4343.          (SELECT artid, columns, creation_script, del_cmd, a.description,
  4344.                  dest_table, filter, ins_cmd, a.name, objid, a.pubid,
  4345.                  a.status, sync_objid, a.type, upd_cmd, NULL, NULL, 0,
  4346.                  a.pre_creation_cmd, NULL, schema_option, dest_owner, 
  4347.                  user_name(o.uid), o.name,
  4348.                  user_name(sync.uid), sync.name,
  4349.                  user_name(fltr.uid), fltr.name
  4350.            FROM syspublications b, 
  4351.                 sysobjects o, 
  4352.                 sysextendedarticlesview a 
  4353.            LEFT JOIN sysobjects fltr on a.filter = fltr.id
  4354.            LEFT JOIN sysobjects sync on a.sync_objid = sync.id
  4355.            WHERE a.name LIKE @article
  4356.              AND a.objid = o.id
  4357.              AND a.pubid = b.pubid
  4358.              AND b.name = @publication)
  4359.     END
  4360.  
  4361.     UPDATE #tab1
  4362.        SET source_table = QUOTENAME(u.name) + '.' + QUOTENAME(o.name)
  4363.       FROM #tab1, sysobjects o, sysusers u
  4364.      WHERE o.id = #tab1.objid
  4365.        AND o.uid = u.uid
  4366.  
  4367.     UPDATE #tab1
  4368.         SET unqua_sync_object = sysobjects.name
  4369.         from sysobjects 
  4370.         where sysobjects.id = sync_objid
  4371.  
  4372.     UPDATE #tab1
  4373.        SET sync_object = QUOTENAME(sysusers.name) + '.' + QUOTENAME(sysobjects.name)
  4374.       FROM sysobjects, sysusers
  4375.      WHERE sysobjects.id = sync_objid
  4376.        AND sysobjects.uid = sysusers.uid
  4377.  
  4378.     UPDATE #tab1 SET filter = (SELECT sysusers.name + '.' + sysobjects.name
  4379.                                  FROM sysobjects, sysusers
  4380.                                 WHERE sysobjects.id = #tab1.old_filter
  4381.                                   AND sysobjects.uid = sysusers.uid)
  4382.       FROM #tab1
  4383.  
  4384.     DECLARE hC  CURSOR LOCAL FAST_FORWARD FOR SELECT name, pubid FROM #tab1
  4385.     OPEN hC
  4386.     FETCH hC INTO @article, @pubid
  4387.     WHILE (@@fetch_status <> -1)
  4388.         BEGIN
  4389.             IF EXISTS (SELECT *
  4390.                          FROM sysextendedarticlesview a, syscolumns b
  4391.                          WHERE 
  4392.                           ( 
  4393.                            convert(bit, convert( varbinary, substring( convert( nvarchar, a.columns ), 16 - floor((colid-1)/16),1 )) & power( 2, ((colid-1)%16))) = 0
  4394.                            OR convert(bit, convert( varbinary, substring( convert( nvarchar, a.columns ), 16 - floor((colid-1)/16),1 )) & power( 2, ((colid-1)%16))) IS NULL
  4395.                           )
  4396.                           AND a.objid = b.id
  4397.                           AND a.name = @article
  4398.                           AND a.pubid = @pubid)
  4399.  
  4400.                 UPDATE #tab1
  4401.                    SET vpartition = 1
  4402.                  WHERE name = @article
  4403.                    AND pubid = @pubid
  4404.  
  4405.             FETCH hC INTO @article, @pubid
  4406.         END
  4407.     CLOSE hC
  4408.     DEALLOCATE hC
  4409.  
  4410.     SELECT 'article id'                = art.artid,
  4411.        'article name'              = name,
  4412.        'base object'                = source_table,
  4413.        'destination object'         = dest_table,
  4414.        'synchronization object'    = sync_object,
  4415.        'type'                      = case 
  4416.                                         when objectproperty(art.objid, 'IsSchemaBound') = 1 and type <> 0x80 then 0x0100 | convert(smallint, type)
  4417.                                         else type 
  4418.                                      end,    
  4419.        -- bit 32 indicates whether or not timestamp is included in partition for queue publications
  4420.        -- It is internal and should be hidden from DMO scripting, since it is not allowed to 
  4421.        -- be set in sp_addarticle
  4422.        -- sp_helparticlecolumns will use that bit to return proper information.
  4423.        'status'                    = status & ~32,
  4424.        'filter'                    = filter,
  4425.        'description'               = description,
  4426.        'insert_command'            = ins_cmd,
  4427.        'update_command'            = upd_cmd,
  4428.        'delete_command'            = del_cmd,
  4429.        'creation script path'      = creation_script,
  4430.        'vertical partition'        = vpartition,
  4431.        'pre_creation_cmd'       = pre_creation_cmd,
  4432.        -- filter_clause is null when @return_filter is 0
  4433.        'filter_clause'           = filter_clause,
  4434.        'schema_option'            = schema_option,
  4435.        'dest_owner'             = dest_owner,
  4436.        'source_owner'           = source_owner,
  4437.        'unqua_source_object'    = unqua_source_object,
  4438.        'sync_object_owner'      = sync_object_owner,
  4439.        'unqualified_sync_object' = unqua_sync_object,
  4440.        'filter_owner'           = filter_owner,
  4441.        'unqua_filter'           = unqua_filter,
  4442.        'auto_identity_range'    = isnull(artupd.identity_support, 0),
  4443.        'publisher_identity_range' = abs(iden.pub_range),
  4444.        'identity_range'    = abs(iden.range),
  4445.        'threshold' = iden.threshold
  4446.       FROM #tab1 art
  4447.         left join sysarticleupdates artupd on art.artid = artupd.artid
  4448.         left join MSpub_identity_range iden on art.objid = iden.objid
  4449.       ORDER BY 2
  4450.  
  4451.     RETURN (0)
  4452. go
  4453.  
  4454. dump tran master with no_log
  4455. go
  4456.  
  4457. EXEC dbo.sp_MS_marksystemobject sp_helparticle
  4458. GO
  4459.  
  4460.  
  4461. print ''
  4462. print 'Creating procedure sp_MSis_col_replicated'
  4463. go
  4464. create procedure sp_MSis_col_replicated @publication sysname, 
  4465.     @article sysname, 
  4466.     @coltype nvarchar(10) = 'timestamp',  -- identity or timestamp or rowguid
  4467.     @colname sysname = NULL OUTPUT 
  4468. as
  4469.     declare @word tinyint, 
  4470.         @bit tinyint, 
  4471.         @mask binary(2), 
  4472.         @mval int,
  4473.         @colword binary(2), 
  4474.         @columns binary(32),
  4475.         @firstcol tinyint, 
  4476.         @colid smallint,
  4477.         @tabid int,
  4478.         @pubid int
  4479.         
  4480.  
  4481.     select @colname = NULL
  4482.  
  4483.     select @pubid = pubid from syspublications where name = @publication
  4484.  
  4485.     select @tabid = objid from sysarticles 
  4486.         where name = @article and pubid = @pubid
  4487.     
  4488.     if @coltype = 'timestamp'
  4489.     begin
  4490.         if ObjectProperty(@tabid, 'TableHasTimestamp') = 1 
  4491.         begin
  4492.  
  4493.             select @colname = name, @colid = colid from syscolumns 
  4494.                 where id = @tabid and type_name(xtype) = 'timestamp' 
  4495.             
  4496.             if @colname is not NULL
  4497.             begin                       
  4498.                 -- check if  timestamp is replicated
  4499.                 --  Obtain the byte offset and the bit offset, then set the
  4500.                 select @columns=columns from sysarticles where name = @article and pubid = @pubid
  4501.                 select @word = CONVERT(tinyint, 16 - FLOOR((@colid-1)/16))
  4502.                 select @bit = (@colid-1) % 16
  4503.                 select @mval = POWER(2, @bit)
  4504.                 select @mask = convert( binary(2), substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) )                                 
  4505.     
  4506.                 -- Fish out the byte we're interested in and save it in a
  4507.                 -- a temporary local variable.  
  4508.                 select @colword = convert( binary(2), SUBSTRING( convert(nchar(16),@columns), @word, 1) )
  4509.     
  4510.                 if convert( smallint, @colword ) & convert( smallint, @mask) = 0 
  4511.                 begin
  4512.                     select @colname = NULL
  4513.                     return (0)
  4514.                 end
  4515.                 else
  4516.                     return (1)
  4517.             end
  4518.             else
  4519.             begin
  4520.                 select @colname = NULL
  4521.                 return (0)
  4522.             end
  4523.         end
  4524.         else
  4525.         begin
  4526.             select @colname = NULL
  4527.             return (0)
  4528.         end
  4529.     end
  4530.     else if @coltype = 'identity'
  4531.     begin
  4532.         if ObjectProperty(@tabid, 'TableHasIdentity') = 1 
  4533.         begin
  4534.             select @colname = name, @colid = colid from syscolumns 
  4535.             where id = @tabid and ColumnProperty(@tabid, name, 'IsIdentity') = 1
  4536.             
  4537.             if @colname is not NULL
  4538.             begin                       
  4539.                 -- check if column is replicated
  4540.                 --  Obtain the byte offset and the bit offset, then set the
  4541.                 select @columns=columns from sysarticles where name = @article and pubid = @pubid
  4542.                 select @word = CONVERT(tinyint, 16 - FLOOR((@colid-1)/16))
  4543.                 select @bit = (@colid-1) % 16
  4544.                 select @mval = POWER(2, @bit)
  4545.                 select @mask = convert( binary(2), substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) )                                 
  4546.  
  4547.                 -- Fish out the byte we're interested in and save it in a
  4548.                 -- a temporary local variable.  
  4549.                 select @colword = convert( binary(2), SUBSTRING( convert(nchar(16),@columns), @word, 1) )
  4550.                 
  4551.                 if convert( smallint, @colword ) & convert( smallint, @mask) = 0 
  4552.                 begin
  4553.                     select @colname = NULL
  4554.                     return (0)
  4555.                 end
  4556.                 else
  4557.                     return (1)
  4558.             end
  4559.             else
  4560.             begin
  4561.                 select @colname = NULL
  4562.                 return (0)
  4563.             end
  4564.         end
  4565.     end
  4566.     else if @coltype = 'rowguid'
  4567.     begin
  4568.         if ObjectProperty(@tabid, 'TableHasRowGuid') = 1 
  4569.         begin
  4570.             select @colname = name, @colid = colid from syscolumns 
  4571.             where id = @tabid and ColumnProperty(@tabid, name, 'IsRowGuidCol') = 1
  4572.             
  4573.             if @colname is not NULL
  4574.             begin                       
  4575.                 -- check if column is replicated
  4576.                 --  Obtain the byte offset and the bit offset, then set the
  4577.                 select @columns=columns from sysarticles where name = @article and pubid = @pubid
  4578.                 select @word = CONVERT(tinyint, 16 - FLOOR((@colid-1)/16))
  4579.                 select @bit = (@colid-1) % 16
  4580.                 select @mval = POWER(2, @bit)
  4581.                 select @mask = convert( binary(2), substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) )                                 
  4582.  
  4583.                 -- Fish out the byte we're interested in and save it in a
  4584.                 -- a temporary local variable.  
  4585.                 select @colword = convert( binary(2), SUBSTRING( convert(nchar(16),@columns), @word, 1) )
  4586.                 
  4587.                 if convert( smallint, @colword ) & convert( smallint, @mask) = 0 
  4588.                 begin
  4589.                     select @colname = NULL
  4590.                     return (0)
  4591.                 end
  4592.                 else
  4593.                     return (1)
  4594.             end
  4595.             else
  4596.             begin
  4597.                 select @colname = NULL
  4598.                 return (0)
  4599.             end
  4600.         end
  4601.  
  4602.         else
  4603.         begin
  4604.             select @colname = NULL
  4605.             return (0)
  4606.         end
  4607.     end
  4608.     else
  4609.     begin
  4610.         select @colname = NULL
  4611.         return (0)    
  4612.     end
  4613. go
  4614.  
  4615. EXEC dbo.sp_MS_marksystemobject sp_MSis_col_replicated
  4616. GO
  4617.  
  4618. print ''
  4619. print 'Creating procedure sp_articlecolumn'
  4620. go
  4621. CREATE PROCEDURE sp_articlecolumn (
  4622.         @publication sysname,           /* The publication name */
  4623.         @article sysname,               /* The article name */
  4624.         @column sysname = NULL,         /* The column name */
  4625.         @operation nvarchar(4) = N'add'      /* Add or delete a column */
  4626.         -- synctran
  4627.         , @refresh_synctran_procs bit = 1      -- refresh synctran procs or not
  4628.         , @ignore_distributor bit = 0
  4629.         -- DDL
  4630.         , @change_active int = 0
  4631.         , @force_invalidate_snapshot bit = 0    /* Force invalidate existing snapshot */
  4632.         , @force_reinit_subscription bit = 0    /* Force reinit subscription */
  4633.  
  4634.         ) 
  4635. AS
  4636. BEGIN
  4637.  
  4638.     /*
  4639.     ** Declarations.
  4640.     */
  4641.  
  4642.     DECLARE @bit tinyint                /* Bit offset */
  4643.             ,@word tinyint               /* word offset */
  4644.             ,@cnt tinyint, @idx tinyint  /* Loop counter, index */
  4645.             ,@columns binary(32)         /* Temporary storage for the converted column */
  4646.             ,@mask binary(2)              /* Bit mask to set the bit on */
  4647.             ,@mval int
  4648.             ,@newword binary(2)
  4649.             ,@oldword binary(2)
  4650.             ,@pubid int                  /* Publication identification number */
  4651.             ,@retcode int                /* Return code for stored procedures */
  4652.             ,@artid int
  4653.             ,@active tinyint
  4654.             ,@objid int            /* Article base table id */    
  4655.             ,@tablename  sysname
  4656.             ,@fSynctranColChanged bit
  4657.             ,@pkkey sysname
  4658.             ,@indid int
  4659.             ,@index_cnt int
  4660.  
  4661.     select @active = 2
  4662.             ,@fSynctranColChanged = 0
  4663.  
  4664.     /*
  4665.     ** Security Check
  4666.     */
  4667.     exec @retcode = dbo.sp_MSreplcheck_publish
  4668.     if @@ERROR <> 0 or @retcode <> 0
  4669.         return(1)
  4670.  
  4671.     /*
  4672.     ** Check to see if the database has been activated for publication.
  4673.     ** Do not check if @ignore_distributor indicates brute force cleanup.
  4674.     */
  4675.  
  4676.     IF ( (SELECT category & 1
  4677.           FROM master..sysdatabases
  4678.          WHERE name = DB_NAME() collate database_default) = 0 )  and ( @ignore_distributor = 0 )
  4679.  
  4680.     BEGIN
  4681.         RAISERROR (14013, 16, -1)
  4682.         RETURN (1)
  4683.     END
  4684.  
  4685.     /*
  4686.     ** Parameter Check:  @publication.
  4687.     ** Make sure that the publication exists and that it conforms to the
  4688.     ** rules for identifiers.
  4689.     */
  4690.  
  4691.     IF @publication IS NULL
  4692.         BEGIN
  4693.             RAISERROR (14043, 16, -1, N'@publication')
  4694.             RETURN (1)
  4695.         END
  4696.  
  4697.     EXECUTE @retcode = dbo.sp_validname @publication
  4698.  
  4699.     IF @retcode <> 0
  4700.             RETURN (1)
  4701.  
  4702.     declare @allow_queued_tran bit
  4703.     declare @allow_sync_tran bit
  4704.  
  4705.     SELECT @pubid = pubid, 
  4706.         @allow_sync_tran = allow_sync_tran,
  4707.         @allow_queued_tran = allow_queued_tran
  4708.         FROM syspublications WHERE name = @publication
  4709.  
  4710.     IF @pubid IS NULL
  4711.         BEGIN
  4712.             RAISERROR (20026, 11, -1, @publication)
  4713.             RETURN (1)
  4714.         END
  4715.     ELSE
  4716.  
  4717.     /*
  4718.     ** Parameter Check:  @article.
  4719.     ** Check to make sure that the article exists in the publication.
  4720.     */
  4721.  
  4722.     IF @article IS NULL
  4723.         BEGIN
  4724.             RAISERROR (14043, 16, -1, N'@article')
  4725.             RETURN (1)
  4726.         END
  4727.  
  4728.     /*
  4729.     EXECUTE @retcode = dbo.sp_validname @article
  4730.  
  4731.     IF @@ERROR <> 0 OR @retcode <> 0
  4732.     RETURN (1)
  4733.     */
  4734.  
  4735.     /*
  4736.     ** Make sure the article exists.
  4737.     */
  4738.     SELECT @artid = artid FROM sysarticles
  4739.        WHERE pubid = @pubid AND name = @article
  4740.     IF @artid IS NULL
  4741.         BEGIN
  4742.             RAISERROR (20027, 11, -1, @article)
  4743.             RETURN (1)
  4744.         END
  4745.  
  4746.  
  4747.     /*
  4748.     ** Error out if this is a not a table based article
  4749.     */
  4750.     IF NOT EXISTS ( SELECT * FROM sysarticles WHERE artid = @artid
  4751.                       AND pubid = @pubid
  4752.                       AND (type & 1) = 1 )
  4753.         BEGIN
  4754.             RAISERROR (14112, 11, -1 )
  4755.             RETURN (1)
  4756.         END
  4757.  
  4758.     /*
  4759.     ** Parameter Check:  @column.
  4760.     ** Check to make sure that the column exists and conforms to the rules
  4761.     ** for identifiers.
  4762.     */
  4763.  
  4764.     /*
  4765.     IF @column IS NOT NULL
  4766.         BEGIN
  4767.             EXECUTE @retcode = dbo.sp_validname @column
  4768.             IF @@ERROR <> 0 OR @retcode <> 0
  4769.             RETURN (1)
  4770.         END
  4771.     */
  4772.  
  4773.     /*
  4774.     ** Parameter Check:  @operation.
  4775.     ** The operation can be either 'add' or 'drop'.
  4776.     */
  4777.  
  4778.     IF LOWER(@operation) NOT IN (N'add', N'drop')
  4779.         BEGIN
  4780.             RAISERROR (14019, 16, -1)
  4781.             RETURN (1)
  4782.         END
  4783.         
  4784.     SELECT @objid = (SELECT objid FROM sysarticles WHERE artid = @artid)
  4785.     SELECT @tablename = OBJECT_NAME(@objid)
  4786.    
  4787.     if @column is not null
  4788.     begin
  4789.         declare @colid    smallint
  4790.         select @colid=colid from syscolumns where id=@objid and name=@column
  4791.         if @colid is null
  4792.         begin
  4793.             RAISERROR (14020, 16, -1)
  4794.             RETURN (1)
  4795.         end
  4796.  
  4797.     if LOWER(@operation) = 'drop'
  4798.     begin        
  4799.         -- Vertical partition is only allowed on table-based article, not IV->table
  4800.             IF OBJECTPROPERTY(@objid, 'IsTable') <> 1
  4801.             BEGIN
  4802.                 RAISERROR (14112, 11, -1 )
  4803.                    RETURN (1)
  4804.             END
  4805.         -- PK column has to be included in vertical partition
  4806.         select @indid = indid from sysindexes where id = @objid and (status & 2048) <> 0    /* PK index */
  4807.         select @index_cnt = 1
  4808.         while (@index_cnt <= 16)
  4809.             begin
  4810.                 select @pkkey = INDEX_COL(@tablename, @indid, @index_cnt)
  4811.                 if @pkkey is NULL
  4812.                     break
  4813.                 if @pkkey=@column
  4814.                     begin
  4815.                         raiserror(21250, 16, -1, @column)
  4816.                         return (1)
  4817.                     end
  4818.                 select @index_cnt = @index_cnt + 1
  4819.             end
  4820.     end
  4821.  
  4822.         -- If the publication is allow_sync_tran, we cannot drop the timestamp
  4823.         -- column from the partition.
  4824.         if (@allow_sync_tran = 1 or @allow_queued_tran = 1) and LOWER(@operation) = N'drop'
  4825.         begin
  4826.             if N'msrepl_tran_version' = @column
  4827.             BEGIN
  4828.                 RAISERROR (21080, 16, -1)
  4829.                 RETURN (1)
  4830.             END
  4831.         end
  4832.  
  4833.         -- Only columns that have default values can be outside the partition
  4834.         -- Note: do check error if it is schema change.
  4835.         if @change_active = 0 and LOWER(@operation)=N'drop' and 
  4836.             (@allow_queued_tran = 1 or @allow_sync_tran = 1) and
  4837.             ColumnProperty(@objid, @column, N'IsIdentity') <> 1 and
  4838.             -- 189 is timestamp.
  4839.             not exists (select * from syscolumns where id = @objid and 
  4840.                 name=@column and (isnullable=1 or xtype = 189)) and
  4841.             not exists (select * from sysconstraints where id=@objid and 
  4842.                 colid=@colid and status & 5 = 5)
  4843.         BEGIN
  4844.             RAISERROR(21165, 16, -1, @column)
  4845.             return (1)
  4846.         END
  4847.     end
  4848.  
  4849.     -- @ignore_distributor is set to 1 when removing replication forcefully. In that
  4850.     -- case, no need to check or reinit
  4851.     if @ignore_distributor = 0
  4852.     begin
  4853.         -- Check if there are snapshot or subscriptions and raiserror if needed.
  4854.         EXECUTE @retcode  = dbo.sp_MSreinit_article
  4855.             @publication = @publication, 
  4856.             @article = @article,
  4857.             @need_new_snapshot = 1,
  4858.             @need_reinit_subscription = 1
  4859.             ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  4860.             ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  4861.             ,@check_only = 1
  4862.         IF @@ERROR <> 0 OR @retcode <> 0
  4863.             return (1)
  4864.     end
  4865.  
  4866.     begin tran
  4867.     save TRANSACTION articlecolumn
  4868.  
  4869.     /*
  4870.     ** Make sure that the columns column is not NULL.
  4871.     */
  4872.  
  4873. --    SELECT @zero = 0x00
  4874.  
  4875.     SELECT @columns = columns
  4876.       FROM sysarticles
  4877.      WHERE artid = @artid
  4878.  
  4879.     IF @columns IS NULL
  4880.         UPDATE sysarticles
  4881.            SET columns = 0x00
  4882.          WHERE artid = @artid
  4883.  
  4884.     /*
  4885.     ** If no columns are specified, or if NULL is specified, set all
  4886.     ** the bits in the 'columns' column so all columns will be included.
  4887.     */
  4888.  
  4889.     IF @column IS NULL
  4890.     BEGIN
  4891.        DECLARE hCartcolumn CURSOR LOCAL FAST_FORWARD FOR
  4892.             SELECT name FROM syscolumns where
  4893.                 id = @objid
  4894.     END
  4895.     ELSE
  4896.     BEGIN
  4897.        DECLARE hCartcolumn CURSOR LOCAL FAST_FORWARD FOR 
  4898.             SELECT @column
  4899.     END
  4900.  
  4901.  
  4902.     OPEN hCartcolumn
  4903.  
  4904.     FETCH hCartcolumn INTO @column
  4905.  
  4906.     WHILE (@@fetch_status <> -1)
  4907.     BEGIN
  4908.  
  4909.         DECLARE @columnid smallint   /* Columnid-1 = bit to set */
  4910.         /*
  4911.         ** Get the column id for this column.  We'll use the column id
  4912.         ** to determine the bit in the 'columns' column.  The bit we want
  4913.         ** is equal to the columnid - 1.
  4914.         */
  4915.  
  4916.         SELECT @columnid = colid
  4917.         FROM syscolumns
  4918.         WHERE id = @objid AND name = @column
  4919.  
  4920.         IF ((@@error <> 0) OR (@columnid IS NULL))
  4921.         BEGIN
  4922.             if @@trancount > 0
  4923.             begin
  4924.                 ROLLBACK TRANSACTION articlecolumn
  4925.                 commit tran
  4926.             end
  4927.             RAISERROR (14020, 16, -1)
  4928.             RETURN (1)
  4929.         END
  4930.  
  4931.  
  4932.         if @allow_queued_tran = 1 and 
  4933.         exists (select * from syscolumns WHERE id = @objid and xtype = 189 and name = @column)
  4934.         begin
  4935.             --
  4936.             -- For queued publication, don't mark the timestamp column in the column bitmap
  4937.             -- Refer to sp_helparticlecolumns
  4938.             --
  4939.             IF lower(@operation) = N'add'
  4940.                 -- Set bit to indicate the timestamp column should be scripted out
  4941.                 -- Also need to set to use explicit column name list at the same time.
  4942.                 update sysarticles set status = (status | 32) | 8  where artid = @artid
  4943.             else
  4944.                 -- Clear the bit
  4945.                 update sysarticles set status = status & ~32 where artid = @artid
  4946.  
  4947.             if @@error <> 0
  4948.             BEGIN
  4949.                 if @@trancount > 0
  4950.                 begin
  4951.                     ROLLBACK TRANSACTION articlecolumn
  4952.                     commit tran
  4953.                 end
  4954.                 RETURN (1)
  4955.             END
  4956.  
  4957.             -- mark for synctran proc refresh
  4958.             select @fSynctranColChanged = 1            
  4959.         end
  4960.         else
  4961.         begin
  4962.  
  4963.             /*
  4964.             ** Obtain the byte offset and the bit offset, then set the
  4965.             ** mask column for the bit we want to turn on.
  4966.             */
  4967.  
  4968.             SELECT @word = CONVERT(tinyint, 16 - FLOOR((@columnid-1)/16))
  4969.             SELECT @bit = (@columnid-1) % 16
  4970.  
  4971.             IF LOWER(@operation) = N'add'
  4972.                 SELECT @mval = POWER(2, @bit)
  4973.             ELSE
  4974.                 SELECT @mval = ~POWER(2, @bit)
  4975.  
  4976.             select @mask = convert( binary(2), substring( convert( nchar(2), convert( binary(4), @mval ) ), 2, 1 ) )
  4977.  
  4978.             /*
  4979.             ** Save the columns column in a temporary local variable so we
  4980.             ** can twiddle the bit and then put it back into the table.
  4981.             */
  4982.  
  4983.             SELECT @columns = columns
  4984.             FROM sysarticles
  4985.             WHERE name = @article AND pubid = @pubid
  4986.             if(@change_active = 2) -- Only post if it came from sp_repladd(drop)column
  4987.             begin
  4988.                 exec sp_replpostcmd 0, @pubid, @artid, 51, @columns
  4989.             end
  4990.  
  4991.             /*
  4992.             ** Fish out the byte we're interested in and save it in a
  4993.             ** a temporary local variable.  If it's NULL, just set it
  4994.             ** to 0.  Then apply the bitwise operator OR to twiddle the
  4995.             ** bit in the old byte and save it in another temporary
  4996.             ** local variable @newbyte.
  4997.             */
  4998.             SELECT @oldword = CONVERT( binary(2), SUBSTRING( CONVERT( nvarchar,@columns), @word, 1) )
  4999.  
  5000.             IF @oldword IS NULL SELECT @oldword = 0x0000
  5001.  
  5002.             IF LOWER(@operation) = N'add'
  5003.                 SELECT @newword = CONVERT(binary(2), convert(smallint, @oldword) | @mask)
  5004.             ELSE
  5005.                 SELECT @newword = CONVERT(binary(2), convert(smallint, @oldword ) & @mask)
  5006.  
  5007.             SELECT @columns = CONVERT(binary(32), STUFF( convert(nchar(16),@columns), @word, 1, convert( nchar(1), @newword)))
  5008.             SELECT @idx = @idx + 1
  5009.  
  5010.             /*
  5011.             ** Update the sysarticles table.  Set the bit appropriately for the selected column
  5012.             */
  5013.  
  5014.             UPDATE sysarticles
  5015.             SET columns = @columns
  5016.             WHERE name = @article
  5017.             AND pubid = @pubid
  5018.  
  5019.             IF @@error <> 0
  5020.             BEGIN
  5021.                 if @@trancount > 0
  5022.                 begin
  5023.                     ROLLBACK TRANSACTION articlecolumn
  5024.                     commit tran
  5025.                 end
  5026.                 RAISERROR (14021, 16, -1)
  5027.                 RETURN (1)
  5028.             END
  5029.  
  5030.             /* 
  5031.             ** if the status has changed, call sp_MSarticlecol to update the publication
  5032.             ** status as appropriate.
  5033.             */
  5034.  
  5035.             IF @oldword != @newword
  5036.             BEGIN
  5037.                 /* Update column published status */
  5038.                 EXECUTE @retcode = dbo.sp_MSarticlecol @artid, @columnid,
  5039.                                         N'publish', @operation
  5040.                 IF (@@error <> 0 OR @retcode <> 0)
  5041.                 BEGIN
  5042.                     if @@trancount > 0
  5043.                     begin
  5044.                         ROLLBACK TRANSACTION articlecolumn
  5045.                         commit tran
  5046.                     end
  5047.                     RAISERROR (14021, 16, -1)
  5048.                     RETURN (1)
  5049.                 END
  5050.                 select @fSynctranColChanged = 1
  5051.             END
  5052.  
  5053.         end -- end of if else block
  5054.  
  5055.         -- fetch the next column
  5056.         FETCH hCartcolumn INTO @column
  5057.  
  5058.     END -- end of while block
  5059.  
  5060.     -- Synctran
  5061.     /*
  5062.     ** If publication is enabled for Synctran and sprocs are auto-generated - regenerate them
  5063.     */
  5064.     declare @autogen_sync_procs_id bit
  5065.         ,@ins_proc_id int, @upd_proc_id int, @del_proc_id int, @upd_trig_id int
  5066.         ,@ins_proc sysname, @upd_proc sysname, @del_proc sysname, @owner sysname, @objname sysname
  5067.         ,@upd_trig sysname
  5068.         ,@sync_pubid int
  5069.         ,@conflict_table_id int, @ins_conflict_proc int
  5070.         ,@cmd nvarchar(4000)
  5071.  
  5072.     select @autogen_sync_procs_id = autogen_sync_procs, @sync_pubid = pubid
  5073.     from syspublications where name = @publication
  5074.  
  5075.     if  @autogen_sync_procs_id = 1 and @refresh_synctran_procs = 1 and @fSynctranColChanged = 1
  5076.     begin
  5077.         -- Drop existing synctran procs
  5078.         select @owner = user_name(OBJECTPROPERTY(objid, N'OwnerId')) from sysarticles a, syspublications p
  5079.         where a.name = @article and
  5080.               p.name = @publication and
  5081.               a.pubid = p.pubid
  5082.  
  5083.         select     @ins_proc_id = sync_ins_proc, 
  5084.                 @upd_proc_id = sync_upd_proc, 
  5085.                 @del_proc_id = sync_del_proc, 
  5086.                 @upd_trig_id = sync_upd_trig,
  5087.                 @conflict_table_id = conflict_tableid,
  5088.                 @ins_conflict_proc = ins_conflict_proc
  5089.         from sysarticleupdates
  5090.             where pubid = @pubid and artid = @artid
  5091.  
  5092.         if @ins_proc_id is not null
  5093.         begin
  5094.             select @objname = object_name(@ins_proc_id)     
  5095.             exec @retcode = dbo.sp_MSdrop_object
  5096.                 @object_name = @objname,
  5097.                 @object_owner = @owner
  5098.             if @@error <> 0 or @retcode <> 0
  5099.                 goto UNDO
  5100.         end
  5101.  
  5102.         if @upd_proc_id is not null
  5103.         begin
  5104.             select @objname = object_name(@upd_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 @del_proc_id is not null
  5113.         begin
  5114.             select @objname = object_name(@del_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 @upd_trig_id is not null
  5123.         begin
  5124.             select @objname = object_name(@upd_trig_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 (@conflict_table_id is not null)
  5133.         begin
  5134.             select @objname = object_name(@conflict_table_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 (@ins_conflict_proc is not null)
  5143.         begin
  5144.             select @objname = object_name(@ins_conflict_proc)     
  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.         -- Now generate new ones        
  5153.         select @ins_proc = N'sp_MSsync_ins_' + SUBSTRING(RTRIM(@article), 1, 100) + N'_' + rtrim(convert(varchar, @sync_pubid))
  5154.         select @upd_proc = N'sp_MSsync_upd_' + SUBSTRING(RTRIM(@article), 1, 100) + N'_' + rtrim(convert(varchar, @sync_pubid))
  5155.         select @del_proc = N'sp_MSsync_del_' + SUBSTRING(RTRIM(@article), 1, 100) + N'_' + rtrim(convert(varchar, @sync_pubid))
  5156.         select @upd_trig = N'sp_MSsync_upd_trig_' + SUBSTRING(RTRIM(@article), 1, 100) + N'_' + rtrim(convert(varchar, @sync_pubid))
  5157.  
  5158.         -- check uniqueness of names and revert to ugly guid-based name if friendly name already exists
  5159.         if exists (select name from sysobjects where name in (@ins_proc, @upd_proc, @del_proc))
  5160.         begin
  5161.             declare @guid_name nvarchar(36)
  5162.             select @guid_name =  convert (nvarchar(36), newid())
  5163.             -- remove '-' from guid name because rpc can't handle '-'
  5164.             select @guid_name = replace (@guid_name,N'-',N'_')
  5165.             select @ins_proc = N'sp_MSsync_ins_' + @guid_name
  5166.             select @upd_proc = N'sp_MSsync_upd_' + @guid_name
  5167.             select @del_proc = N'sp_MSsync_del_' + @guid_name
  5168.             select @upd_trig = N'sp_MSsync_upd_trig' + @guid_name
  5169.         end
  5170.  
  5171.         if @ins_proc IS NULL
  5172.         begin
  5173.             RAISERROR (14043, 11, -1, N'@ins_proc')
  5174.             goto UNDO
  5175.         end
  5176.  
  5177.         if @upd_proc IS NULL
  5178.         begin
  5179.             RAISERROR (14043, 11, -1, N'@upd_proc')
  5180.             goto UNDO
  5181.         end
  5182.  
  5183.         if @del_proc IS NULL
  5184.         begin
  5185.             RAISERROR (14043, 11, -1, N'@del_proc')
  5186.             goto UNDO
  5187.         end
  5188.  
  5189.         if @upd_trig IS NULL
  5190.         begin
  5191.             RAISERROR (14043, 11, -1, N'@del_proc')
  5192.             goto UNDO
  5193.         end
  5194.  
  5195.         exec @retcode = dbo.sp_MSgen_sync_tran_procs @publication, @article, @ins_proc, @upd_proc, @del_proc, @upd_trig
  5196.  
  5197.         IF @@ERROR <> 0 OR @retcode <> 0
  5198.             goto UNDO
  5199.  
  5200.         --retrieve sproc id's, fail if they don't exist
  5201.         SELECT @ins_proc_id = id FROM sysobjects WHERE name = @ins_proc
  5202.         SELECT @upd_proc_id = id FROM sysobjects WHERE name = @upd_proc
  5203.         SELECT @del_proc_id = id FROM sysobjects WHERE name = @del_proc
  5204.         SELECT @upd_trig_id = id FROM sysobjects WHERE name = @upd_trig
  5205.  
  5206.         IF (@ins_proc_id IS NULL) OR (@upd_proc_id IS NULL) OR (@del_proc_id IS NULL)
  5207.         BEGIN
  5208.             if @ins_proc_id IS NULL RAISERROR (20500, 16, 1, @ins_proc)
  5209.             if @upd_proc_id IS NULL RAISERROR (20500, 16, 1, @upd_proc)
  5210.             if @del_proc_id IS NULL RAISERROR (20500, 16, 1, @del_proc)
  5211.             if @upd_trig_id IS NULL RAISERROR (20500, 16, 1, @upd_trig)
  5212.             goto UNDO
  5213.         END
  5214.  
  5215.         -- perform update in sysarticleupdates
  5216.         update sysarticleupdates set sync_ins_proc = @ins_proc_id, sync_upd_proc = @upd_proc_id, 
  5217.             sync_del_proc = @del_proc_id,
  5218.             sync_upd_trig = @upd_trig_id
  5219.         where pubid = @pubid and artid = @artid
  5220.         if @@error <> 0
  5221.             goto UNDO
  5222.  
  5223.  
  5224.         --
  5225.         -- create the conflict tran table and table if necessary
  5226.         --
  5227.         if (@allow_queued_tran = 1)
  5228.         begin
  5229.             exec @retcode = dbo.sp_MSmakeconflicttable @article, @publication, 0
  5230.             IF (@@ERROR != 0 OR @retcode != 0)
  5231.                 goto UNDO
  5232.             exec @retcode = dbo.sp_MSmaketrancftproc @article, @publication
  5233.             IF (@@ERROR != 0 OR @retcode != 0)
  5234.                 goto UNDO
  5235.         end 
  5236.         
  5237.         IF @@ERROR <> 0
  5238.         BEGIN
  5239.             RAISERROR (20501, 16, -1)
  5240.             goto UNDO
  5241.          END
  5242.     end
  5243.     -- end synctran
  5244.  
  5245.     -------------------------------------------------------------------
  5246.     -- active article fixups
  5247.     -------------------------------------------------------------------
  5248.  
  5249.     if @change_active<> 0 and @fSynctranColChanged = 1 or
  5250.         -- Besides schema change, we automatically refresh article view if there are 
  5251.         -- subscriptions. We don't refresh the article view otherwise to avoid the view
  5252.         -- being dropped and recreated when adding columns into the partition during
  5253.         -- the creation of the article.
  5254.         exists (select * from syssubscriptions where artid = @artid and
  5255.             srvid >= 0)
  5256.     BEGIN
  5257.         -----------------------------------
  5258.         -- regenerate the article view  
  5259.         -----------------------------------
  5260.  
  5261.         declare @view_name nvarchar(386)
  5262.         declare @filter_clause nvarchar(4000)
  5263.         declare @sync_objid int
  5264.         declare @art_type tinyint
  5265.  
  5266.         select @sync_objid = sa.sync_objid, @filter_clause = sa.filter_clause, @art_type = sa.type
  5267.                              FROM sysarticles sa JOIN syspublications sp ON sa.pubid = sp.pubid
  5268.                              WHERE sa.name = @article 
  5269.                              AND sp.name = @publication
  5270.         -- Only invoke sp_articleview if not manual view and not manual filter
  5271.         if ( @art_type & 0x4 <> 4 and @art_type & 0x2 <> 2 )
  5272.         begin 
  5273.             select @view_name = object_name( @sync_objid )
  5274.  
  5275.             exec @retcode = dbo.sp_articleview @publication = @publication, 
  5276.                                             @article = @article,
  5277.                                             @view_name = @view_name,
  5278.                                             @filter_clause = @filter_clause,
  5279.                                             @change_active = @change_active,
  5280.                                             @force_invalidate_snapshot = @force_invalidate_snapshot,
  5281.                                             @force_reinit_subscription = @force_reinit_subscription
  5282.  
  5283.             IF @@ERROR <> 0 OR @retcode <> 0
  5284.                     goto UNDO
  5285.         end
  5286.     END
  5287.  
  5288.     -- sp_repldropcolumn used @change_active = 2 to prepare, don't invalidate or reinitialize
  5289.     if @change_active <> 2     and
  5290.         -- @ignore_distributor is set to 1 when removing replication forcefully. In that
  5291.         -- case, no need to check or reinit
  5292.         @ignore_distributor = 0
  5293.     begin
  5294.         -- Have to call this stored procedure to invalidate existing snapshot or reint
  5295.         -- subscriptions if needed
  5296.         EXECUTE @retcode  = dbo.sp_MSreinit_article
  5297.             @publication = @publication, 
  5298.             @article = @article,
  5299.             @need_new_snapshot = 1,
  5300.             @need_reinit_subscription = 1
  5301.             ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  5302.             ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  5303.         IF @@ERROR <> 0 OR @retcode <> 0
  5304.             GOTO UNDO
  5305.     end
  5306.  
  5307.     /*
  5308.     ** Force the article cache to be refreshed with the new definition.
  5309.     ** Nothing to flush if brute force cleanup.
  5310.     */
  5311.     if ( @ignore_distributor = 0 )
  5312.         EXECUTE dbo.sp_replflush
  5313.  
  5314.  
  5315.     COMMIT TRANSACTION
  5316. END
  5317. return (0)
  5318. UNDO:
  5319.     if @@trancount > 0
  5320.     begin
  5321.         ROLLBACK TRANSACTION articleview
  5322.         commit tran
  5323.     end
  5324.     RETURN (1)
  5325. go
  5326.  
  5327. EXEC dbo.sp_MS_marksystemobject sp_articlecolumn
  5328. GO
  5329.  
  5330. print ''
  5331. print 'Creating procedure sp_helparticlecolumns'
  5332. go
  5333. CREATE PROCEDURE sp_helparticlecolumns (
  5334.     @publication sysname,            /* The publication name */
  5335.     @article    sysname              /* The article name */
  5336.     ) AS
  5337.  
  5338.     /*
  5339.     ** Declarations.
  5340.     */
  5341.  
  5342.     DECLARE @columns binary(32)
  5343.     DECLARE @pubid int
  5344.     DECLARE @retcode int
  5345.  
  5346.     /*
  5347.     ** Security Check. To public.
  5348.     */
  5349.  
  5350.     /*
  5351.     ** Parameter Check: @article.
  5352.     ** The @article name must conform to the rules for identifiers.
  5353.     */
  5354.  
  5355.     IF @article IS NULL
  5356.         BEGIN
  5357.             RAISERROR (14043, 16, -1, '@article')
  5358.             RETURN (1)
  5359.         END
  5360.     
  5361.     /*
  5362.     EXECUTE @retcode = dbo.sp_validname @article
  5363.  
  5364.     IF @retcode <> 0
  5365.     RETURN (1)
  5366.     */
  5367.  
  5368.     /*
  5369.     ** Parameter Check: @publication.
  5370.     ** The @publication name must conform to the rules for identifiers.
  5371.     */
  5372.  
  5373.     IF @publication IS NULL
  5374.         BEGIN
  5375.             RAISERROR (14043, 16, -1, '@publication')
  5376.             RETURN (1)
  5377.         END
  5378.     
  5379.     EXECUTE @retcode = dbo.sp_validname @publication
  5380.  
  5381.     IF @retcode <> 0
  5382.     RETURN (1)
  5383.     
  5384.     /*
  5385.     ** Get the pubid.
  5386.     */
  5387.  
  5388.     SELECT @pubid = pubid FROM syspublications WHERE name = @publication
  5389.  
  5390.     IF @pubid IS NULL
  5391.         BEGIN
  5392.             RAISERROR (14043, 11, -1, '@pubid')
  5393.             RETURN (1)
  5394.         END
  5395.  
  5396.     /*
  5397.     ** Parameter Check:  @article, @publication.
  5398.     ** Check to make sure that the article exists in this publication.
  5399.     */
  5400.  
  5401.     IF NOT EXISTS (SELECT *
  5402.                      FROM sysextendedarticlesview
  5403.                     WHERE pubid = @pubid
  5404.                       AND name = @article)
  5405.         BEGIN
  5406.             RAISERROR (20027, 11, -1, @article)
  5407.             RETURN (1)
  5408.         END
  5409.  
  5410.  
  5411.     /*
  5412.     ** Error out if this is a not a table based article
  5413.     */
  5414.     IF NOT EXISTS ( SELECT * FROM sysarticles WHERE name = @article
  5415.                           AND pubid = @pubid
  5416.                           AND (type & 1) = 1 )
  5417.         BEGIN
  5418.             RAISERROR (14112, 11, -1 )
  5419.             RETURN (1)
  5420.         END
  5421.  
  5422.     declare @status tinyint
  5423.     declare @objid int
  5424.  
  5425.     SELECT @columns = columns, @status = status, @objid = objid
  5426.       FROM sysarticles
  5427.      WHERE name = @article
  5428.        AND pubid = @pubid
  5429.  
  5430.     -- Get the timestamp column id
  5431.  
  5432.     SELECT 'column id' = colid,
  5433.            'column'    = name,
  5434.            -- 189 is timestamp col
  5435.            -- When the status is set, return timestamp col as published to DMO 
  5436.            -- although it is not in the bitmap used by
  5437.            -- the logreader. Thus, the timestmap will be scripted out and created at the subscriber
  5438.            -- but the value will be generated by subscriber not the logreader.
  5439.            -- 32 is the status bit of keeping timestamp
  5440.            'published' = case xtype when 189
  5441.                 then convert(bit, @status & 32)
  5442.                 else convert(bit, 0) end |
  5443.                 convert(bit, convert( varbinary, substring( convert( nvarchar, @columns ), 16 - floor((colid-1)/16),1 )) & power( 2, ((colid-1)%16)))
  5444.       FROM syscolumns
  5445.      WHERE id = @objid
  5446. go
  5447.  
  5448. EXEC dbo.sp_MS_marksystemobject sp_helparticlecolumns
  5449. GO
  5450.  
  5451. print ''
  5452. print 'Creating procedure sp_helppublication'
  5453. go
  5454.  
  5455.  
  5456. CREATE PROCEDURE sp_helppublication (
  5457.         @publication sysname = '%',     /* The publication name */
  5458.         @found int = 23456 OUTPUT            /* a flag indicate returning row */
  5459.         ) AS
  5460.  
  5461.     SET NOCOUNT ON
  5462.  
  5463.     /*
  5464.     ** Declarations.
  5465.     */
  5466.  
  5467.     DECLARE @pubid      int
  5468.     DECLARE @has_subscription bit
  5469.     DECLARE @retcode int
  5470.     DECLARE @no_row bit
  5471.     DECLARE @publish_bit int
  5472.     
  5473.     SELECT @publish_bit = 1
  5474.     
  5475.     /*
  5476.     ** Check if the database is published.
  5477.     */
  5478.     IF NOT EXISTS (SELECT * FROM master.dbo.sysdatabases
  5479.         WHERE name = db_name() collate database_default
  5480.         AND (category & @publish_bit) = @publish_bit)
  5481.         RETURN(0)
  5482.  
  5483.     /*
  5484.     ** Security Check. To public.
  5485.     */
  5486.  
  5487.     /*
  5488.     ** Initializations.
  5489.     */
  5490.     IF @found = 23456 
  5491.     BEGIN
  5492.         SELECT @no_row=0
  5493.     END
  5494.     ELSE
  5495.     BEGIN
  5496.         SELECT @no_row=1
  5497.     END
  5498.  
  5499.     /*
  5500.     ** Parameter Check:  @publication.
  5501.     ** Check to make sure that there are some publications
  5502.     ** to display.
  5503.     */
  5504.  
  5505.     IF @publication IS NULL
  5506.         BEGIN
  5507.             RAISERROR (14043, 16, -1, '@publication')
  5508.             RETURN (1)
  5509.         END
  5510.     
  5511.     IF @publication <> '%'
  5512.         BEGIN
  5513.             
  5514.             EXECUTE @retcode = dbo.sp_validname @publication
  5515.  
  5516.             IF @retcode <> 0
  5517.             RETURN (1)
  5518.         END
  5519.  
  5520.     IF  NOT EXISTS (SELECT * FROM syspublications
  5521.         WHERE name like @publication)
  5522.  
  5523.     BEGIN
  5524.         SELECT @found = 0
  5525.         RETURN (0) 
  5526.     END
  5527.     ELSE
  5528.     BEGIN
  5529.         SELECT @found = 1
  5530.         IF @no_row <>0
  5531.             RETURN(0)
  5532.     END
  5533.  
  5534.     SELECT 'pubid'                  = pubid,
  5535.            'name'                   = name,
  5536.            'restricted'             = 0,
  5537.            'status'                 = status,
  5538.            -- using 'task' is for backward compatibilty
  5539.            'task'                   = convert(int, 1),
  5540.            'replication frequency'  = repl_freq,
  5541.            'synchronization method' = sync_method,
  5542.            'description'            = description,
  5543.            'immediate_sync'            = immediate_sync,
  5544.            'enabled_for_internet'    = enabled_for_internet,
  5545.            'allow_push'             = allow_push,
  5546.            'allow_pull'             = allow_pull,
  5547.            'allow_anonymous'        = allow_anonymous,
  5548.            'independent_agent'        = independent_agent,
  5549.            'immediate_sync_ready'    = immediate_sync_ready,
  5550.            -- SyncTran
  5551.            'allow_sync_tran'        = allow_sync_tran,
  5552.            'autogen_sync_procs'        = autogen_sync_procs,
  5553.            'snapshot_jobid'         = snapshot_jobid,
  5554.            'retention'              = retention,
  5555.            'has subscription'       = case when EXISTS (select * from syssubscriptions where artid in 
  5556.                                       (select artid from sysextendedarticlesview where pubid = outter.pubid ) )
  5557.                                       then 1 else 0 end,
  5558.            'allow_queued_tran'      = allow_queued_tran,
  5559.            -- Portable snapshot
  5560.            'snapshot_in_defaultfolder'      = snapshot_in_defaultfolder,
  5561.            'alt_snapshot_folder'    = alt_snapshot_folder,
  5562.            -- Pre/post-snapshot commands
  5563.            'pre_snapshot_script'    = pre_snapshot_script,
  5564.            'post_snapshot_script'   = post_snapshot_script,
  5565.            -- Snapshot compression
  5566.            'compress_snapshot'      = compress_snapshot,
  5567.            -- Post 7.0 ftp support
  5568.            'ftp_address'            = ftp_address,
  5569.            'ftp_port'               = ftp_port,
  5570.            'ftp_subdirectory'       = ftp_subdirectory,
  5571.            'ftp_login'              = ftp_login,
  5572.            'allow_dts'                = allow_dts,
  5573.            'allow_subscription_copy'  = allow_subscription_copy,
  5574.            -- 7.5 Queued updates
  5575.            'centralized_conflicts'     = centralized_conflicts, 
  5576.            'conflict_retention'        = conflict_retention, 
  5577.            'conflict_policy'        = conflict_policy,
  5578.            'queue_type'                = queue_type,
  5579.         'backward_comp_level' = backward_comp_level,
  5580.         'publish_to_AD' =        case when ad_guidname is NULL then 0 else 1 end 
  5581.       FROM syspublications outter
  5582.      WHERE name LIKE @publication
  5583.      ORDER BY name
  5584.  
  5585.     RETURN (0)
  5586. go
  5587.  
  5588. EXEC dbo.sp_MS_marksystemobject sp_helppublication
  5589. GO
  5590.  
  5591. -- sp_helppublication_snapshot not used anymore
  5592.  
  5593. print ''
  5594. print 'Creating procedure sp_helpsubscription'
  5595. go
  5596.  
  5597. CREATE PROCEDURE sp_helpsubscription
  5598.     @publication sysname = '%',    /* The publication name */
  5599.     @article sysname = '%',        /* The article name */
  5600.     @subscriber sysname = N'%',      /* The subscriber name */
  5601.     @destination_db sysname = '%',
  5602.     @found int = 23456 OUTPUT
  5603.     AS
  5604.  
  5605.     SET NOCOUNT ON
  5606.  
  5607.     /*
  5608.     ** Declarations.
  5609.     */
  5610.  
  5611.     DECLARE @retcode int
  5612.     DECLARE @subscriber_bit smallint
  5613.     DECLARE @no_row bit
  5614.     DECLARE @srvid smallint
  5615.     DECLARE @pubid int
  5616.     DECLARE @artid int
  5617.     DECLARE @immediate_sync bit
  5618.     DECLARE @subscription_type_id int
  5619.     DECLARE @sync_typeid int
  5620.     DECLARE @publish_bit int
  5621.     DECLARE @orig_publication sysname    
  5622.     DECLARE @full_subscription bit
  5623.  
  5624.     DECLARE @distributor    sysname
  5625.     DECLARE @distributiondb sysname
  5626.     DECLARE @distproc       NVARCHAR(255)
  5627.     DECLARE @dbname         sysname    
  5628.  
  5629.     SELECT @publish_bit = 1
  5630.     SELECT @distributor = NULL
  5631.     SELECT @distributiondb = NULL
  5632.     SELECT @distproc = NULL
  5633.     SELECT @dbname = NULL
  5634.     SELECT @orig_publication = @publication
  5635.  
  5636.     /* Security check. To public. */
  5637.  
  5638.     /*
  5639.     ** Check if the database is published.
  5640.     */
  5641.     IF NOT EXISTS (SELECT * FROM master..sysdatabases
  5642.                     WHERE name = db_name() collate database_default
  5643.                       AND (category & @publish_bit) = @publish_bit)
  5644.         RETURN(0)
  5645.  
  5646.     /*
  5647.     ** Initializations of @now_row.
  5648.     */
  5649.     IF @found = 23456 
  5650.     BEGIN
  5651.         SELECT @no_row=0
  5652.     END
  5653.     ELSE
  5654.     BEGIN
  5655.         SELECT @no_row=1
  5656.     END
  5657.  
  5658.     /*
  5659.     ** Initializations.
  5660.     */
  5661.     SELECT @subscriber_bit = 4
  5662.  
  5663.     /*
  5664.     ** Parameter Check:  @subscriber.
  5665.     */
  5666.     IF @subscriber IS NULL
  5667.         BEGIN
  5668.             RAISERROR (14043, 16, -1, '@subscriber')
  5669.             RETURN (1)
  5670.         END
  5671.  
  5672.     /*
  5673.     ** Parameter Check:  @subscriber.
  5674.     ** Check if remote server is defined as a subscription server, and
  5675.     ** that the name conforms to the rules for identifiers.
  5676.     */
  5677.  
  5678.     IF @subscriber <> '%'
  5679.         BEGIN
  5680.  
  5681.             EXECUTE @retcode = dbo.sp_validname @subscriber
  5682.             select @subscriber = UPPER(@subscriber)
  5683.  
  5684.             IF @retcode <> 0
  5685.         RETURN (1)
  5686.  
  5687.             IF NOT EXISTS (SELECT *
  5688.                              FROM master..sysservers
  5689.                             WHERE UPPER(srvname) = UPPER(@subscriber) collate database_default
  5690.                               AND (srvstatus & @subscriber_bit) <> 0)
  5691.                 BEGIN
  5692.                     RAISERROR (14010, 16, -1)
  5693.                     RETURN (1)
  5694.                 END
  5695.         END
  5696.  
  5697.     /*
  5698.     ** Parameter Check:  @publication.
  5699.     ** If the publication name is specified, check to make sure that it
  5700.     ** conforms to the rules for identifiers and that the publication
  5701.     ** actually exists.  Disallow NULL.
  5702.     */
  5703.  
  5704.     IF @publication IS NULL
  5705.         BEGIN
  5706.             RAISERROR (14043, 16, -1, '@publication')
  5707.             RETURN (1)
  5708.         END
  5709.  
  5710.     IF @publication <> '%'
  5711.         BEGIN
  5712.  
  5713.             EXECUTE @retcode = dbo.sp_validname @publication
  5714.  
  5715.             IF @retcode <> 0
  5716.                 RETURN (1)
  5717.  
  5718.             IF NOT EXISTS (SELECT * FROM syspublications WHERE name = @publication)
  5719.                 BEGIN
  5720.                    RAISERROR (20026, 11, -1, @publication)
  5721.                    RETURN (1)
  5722.                 END
  5723.  
  5724.         END
  5725.  
  5726.     /*
  5727.     ** Parameter Check:  @article.
  5728.     ** If the article name is specified, check to make sure that it
  5729.     ** conforms to the rules for identifiers and that the article
  5730.     ** actually exists.  Disallow NULL.
  5731.     **
  5732.     ** If @article is 'all', only return one entry for the whole publication
  5733.     ** for full subscriptions (subscriptions inlcluding all the articles in a
  5734.     ** publication).
  5735.     ** 
  5736.     */
  5737.  
  5738.     IF @article IS NULL
  5739.         BEGIN
  5740.             RAISERROR (14043, 16, -1, '@article')
  5741.             RETURN (1)
  5742.         END
  5743.  
  5744.     IF LOWER(@article) <> 'all' 
  5745.     BEGIN
  5746.         IF @article <> '%'
  5747.             BEGIN
  5748.                 
  5749.                 /*
  5750.                 EXECUTE @retcode = dbo.sp_validname @article
  5751.  
  5752.                 IF @retcode <> 0
  5753.                 RETURN (1)
  5754.                 */
  5755.  
  5756.                 IF NOT EXISTS (SELECT *
  5757.                                  FROM sysextendedarticlesview
  5758.                                 WHERE name = @article
  5759.                                   AND pubid IN (SELECT pubid
  5760.                                                   FROM syspublications
  5761.                                                  WHERE name LIKE @publication))
  5762.                     BEGIN
  5763.                         RAISERROR (20027, 11, -1, @article)
  5764.                         RETURN (1)
  5765.                     END
  5766.  
  5767.             END
  5768.  
  5769.  
  5770.         IF EXISTS (SELECT * 
  5771.               FROM syssubscriptions sub,
  5772.                    master..sysservers ss,
  5773.                    syspublications pub,
  5774.                    sysextendedarticlesview art
  5775.              WHERE ((@subscriber = N'%') OR (ss.srvname = @subscriber collate database_default))
  5776.                AND sub.srvid = ss.srvid
  5777.                AND pub.name LIKE @publication
  5778.                AND art.name LIKE @article
  5779.                AND art.pubid = pub.pubid
  5780.                AND sub.artid = art.artid
  5781.                AND ((@destination_db = N'%') OR (sub.dest_db = @destination_db))
  5782.                AND (sub.login_name = suser_sname(suser_sid()) OR 
  5783.                     is_srvrolemember('sysadmin') = 1 OR
  5784.                     is_member ('db_owner') = 1)
  5785.                 )
  5786.  
  5787.         BEGIN
  5788.             SELECT @found = 1
  5789.             IF @no_row <> 0 RETURN (0)
  5790.         END
  5791.         ELSE
  5792.         BEGIN
  5793.             SELECT @found = 0
  5794.             RETURN(0)
  5795.         END
  5796.     END
  5797.  
  5798. /*
  5799.         SELECT 'subscriber'           = ss.srvname,
  5800.                'publication'          = pub.name,
  5801.                'article'              = art.name,
  5802.                'destination database' = sub.dest_db,
  5803.                'subscription status'  = sub.status,
  5804.                'synchronization type' = sub.sync_type
  5805.           FROM syssubscriptions sub,
  5806.                master..sysservers ss,
  5807.                syspublications pub,
  5808.                sysextendedarticlesview art
  5809.          WHERE UPPER(ss.srvname) LIKE UPPER(@subscriber) collate database_default
  5810.            AND sub.srvid = ss.srvid
  5811.            AND pub.name LIKE @publication collate database_default
  5812.            AND art.name LIKE @article collate database_default
  5813.            AND art.pubid = pub.pubid
  5814.            AND sub.artid = art.artid
  5815.            AND (sub.login_name = suser_sname(suser_sid()) collate database_default OR 
  5816.                     is_srvrolemember('sysadmin') = 1 OR
  5817.                     is_member ('db_owner') = 1)
  5818.                 )
  5819.          ORDER BY subscriber, publication, article
  5820. */    
  5821.  
  5822.     CREATE TABLE #helpsubscription 
  5823.     (
  5824.     /* Info that will be returned */
  5825.     subscriber sysname collate database_default not null,
  5826.     publication sysname collate database_default not null,
  5827.     article sysname collate database_default not null,
  5828.     destination_db sysname collate database_default not null,
  5829.     status tinyint NOT NULL,
  5830.     sync_type tinyint NOT NULL,
  5831.     subscription_type int NOT NULL,
  5832.     full_subscription bit NOT NULL, /* full subscription or not */
  5833.     distribution_jobid binary(16) NULL,
  5834.     subscription_name nvarchar(255) collate database_default not null,
  5835.     -- SyncTran
  5836.     update_mode int NOT NULL,
  5837.     loopback_detection bit not null
  5838.     )
  5839.  
  5840.  
  5841.     /* Open a CURSOR LOCAL FOR subscriber/destination_db and publication pair 
  5842.     **
  5843.     ** Get subscriptions
  5844.     ** sa or dbo can see every subscriptions while
  5845.     ** others only see their own.
  5846.     */
  5847.  
  5848.     /* 
  5849.     ** Performance Optimization: Eliminate the 'LIKE' clause for publication name.
  5850.     **                           Empirical evidence shows almost 50% speed improvement when
  5851.     **                           opening the cursor if publication name is provided.
  5852.     */
  5853.     IF (@publication <> '%')
  5854.         DECLARE hChelpsubscription_pub CURSOR LOCAL FAST_FORWARD FOR
  5855.             SELECT DISTINCT ss.srvname,
  5856.                    pub.name,
  5857.                    sub.dest_db,
  5858.                    pub.pubid,
  5859.                    sub.srvid,
  5860.                    pub.immediate_sync
  5861.               FROM syssubscriptions sub,
  5862.                    master..sysservers ss,
  5863.                    syspublications pub,
  5864.                    sysextendedarticlesview art
  5865.              WHERE ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber) collate database_default))
  5866.                AND sub.srvid = ss.srvid
  5867.                AND pub.name = @publication collate database_default
  5868.                AND art.pubid = pub.pubid
  5869.                AND sub.artid = art.artid
  5870.                AND ((@destination_db = N'%') OR (sub.dest_db = @destination_db))
  5871.                AND (sub.login_name = suser_sname(suser_sid()) OR 
  5872.                         is_srvrolemember('sysadmin') = 1 OR
  5873.                         is_member ('db_owner') = 1)       
  5874.                FOR READ ONLY
  5875.     ELSE 
  5876.         DECLARE hChelpsubscription_pub CURSOR LOCAL FAST_FORWARD FOR
  5877.             SELECT DISTINCT ss.srvname,
  5878.                    pub.name,
  5879.                    sub.dest_db,
  5880.                    pub.pubid,
  5881.                    sub.srvid,
  5882.                    pub.immediate_sync
  5883.               FROM syssubscriptions sub,
  5884.                    master..sysservers ss,
  5885.                    syspublications pub,
  5886.                    sysextendedarticlesview art
  5887.              WHERE ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber) collate database_default))
  5888.                AND sub.srvid = ss.srvid
  5889.                AND art.pubid = pub.pubid
  5890.                AND sub.artid = art.artid
  5891.                AND ((@destination_db = N'%') OR (sub.dest_db = @destination_db))
  5892.                AND (sub.login_name = suser_sname(suser_sid()) OR 
  5893.                         is_srvrolemember('sysadmin') = 1 OR
  5894.                         is_member ('db_owner') = 1)       
  5895.                FOR READ ONLY
  5896.  
  5897.     OPEN hChelpsubscription_pub
  5898.     FETCH hChelpsubscription_pub INTO @subscriber, @publication, 
  5899.         @destination_db, @pubid, @srvid, @immediate_sync
  5900.         
  5901.     WHILE (@@fetch_status <> -1)
  5902.     BEGIN
  5903.  
  5904.         /* 
  5905.         ** Is it a full subscription ? i.e. Does it include all the articles? 
  5906.         **
  5907.         */
  5908.  
  5909.         IF NOT EXISTS (SELECT * FROM sysextendedarticlesview art WHERE
  5910.                 art.pubid = @pubid and 
  5911.                 NOT EXISTS (SELECT * from syssubscriptions sub WHERE
  5912.                     sub.artid = art.artid and
  5913.                     sub.srvid = @srvid and
  5914.                     sub.dest_db = @destination_db))
  5915.         BEGIN
  5916.             /* Do all the subscriptions on the publication have same
  5917.             ** sync_type and subscription_type ?
  5918.             */
  5919.   
  5920.               /* 
  5921.             ** Get subscription type on the publication
  5922.             */ 
  5923.             SELECT @subscription_type_id = subs.subscription_type,
  5924.                 @sync_typeid = subs.sync_type 
  5925.                 FROM 
  5926.                 sysextendedarticlesview art, syssubscriptions subs  
  5927.                 WHERE
  5928.                 art.pubid = @pubid AND
  5929.                 subs.srvid = @srvid AND
  5930.                 subs.dest_db = @destination_db AND
  5931.                 subs.artid = art.artid
  5932.  
  5933.  
  5934.             /* 
  5935.             ** if the subscription all have the same subscription type
  5936.             ** and sync_type
  5937.             */
  5938.             IF NOT EXISTS (SELECT * from 
  5939.                 sysextendedarticlesview art, syssubscriptions subs where 
  5940.                 art.pubid = @pubid AND
  5941.                 subs.srvid = @srvid AND
  5942.                 subs.dest_db = @destination_db AND
  5943.                 subs.artid = art.artid AND
  5944.                 (subscription_type <> @subscription_type_id OR
  5945.                 sync_type <> @sync_typeid))
  5946.                 
  5947.  
  5948.                 SELECT @full_subscription = 1
  5949.             ELSE
  5950.                 SELECT @full_subscription = 0
  5951.         END
  5952.         ELSE
  5953.         BEGIN
  5954.             SELECT @full_subscription = 0
  5955.         END
  5956.             
  5957.         /* 
  5958.         ** If it is a full subscription and the @article is 'all',
  5959.         ** only return one entry for the whole publication.
  5960.         ** Always return one row per publication if @article is 'ALL'
  5961.         */
  5962.         IF    LOWER(@article) = 'all'
  5963.         BEGIN    
  5964.             INSERT INTO #helpsubscription 
  5965.                 SELECT TOP 1 @subscriber, @publication, @article, @destination_db,
  5966.                     sub.status, sub.sync_type, sub.subscription_type,
  5967.                     @full_subscription, sub.distribution_jobid,
  5968.                     @subscriber + ':' + @destination_db  ,
  5969.                     -- NOTE: For Queued case: we will always return 2/3 for the 4/5 case
  5970.                     -- since we overload update_mode based on queue_type
  5971.                     case     when sub.update_mode = 4 then 2
  5972.                             when sub.update_mode = 5 then 3
  5973.                             else sub.update_mode
  5974.                     end,
  5975.                     sub.loopback_detection
  5976.                     -- end SyncTran
  5977.                     FROM syssubscriptions sub, sysextendedarticlesview art 
  5978.                     WHERE sub.srvid = @srvid AND
  5979.                         sub.dest_db = @destination_db AND
  5980.                         sub.artid = art.artid and
  5981.                         art.pubid = @pubid
  5982.         END
  5983.         ELSE
  5984.         BEGIN
  5985.             /*
  5986.             ** Get subscriptions
  5987.             ** sa or dbo can see every subscriptions while
  5988.             ** others only see their own.
  5989.             */
  5990.  
  5991.             INSERT INTO #helpsubscription 
  5992.                 SELECT    @subscriber, @publication, art.name, @destination_db,
  5993.                     sub.status, sub.sync_type, sub.subscription_type,
  5994.                     @full_subscription, sub.distribution_jobid,
  5995.                     @subscriber + ':' + @destination_db + ':' + art.name,
  5996.                     -- NOTE: For Queued case: we will always return 2/3 for the 4/5 case
  5997.                     -- since we overload update_mode based on queue_type
  5998.                     case     when sub.update_mode = 4 then 2
  5999.                             when sub.update_mode = 5 then 3
  6000.                             else sub.update_mode
  6001.                     end,
  6002.                     sub.loopback_detection
  6003.                     -- end SyncTran
  6004.                     FROM
  6005.                     syssubscriptions sub, sysextendedarticlesview art WHERE
  6006.                         sub.srvid = @srvid AND
  6007.                         sub.dest_db = @destination_db AND
  6008.                         art.pubid = @pubid AND
  6009.                         art.name LIKE @article AND
  6010.                         sub.artid = art.artid AND
  6011.                         (sub.login_name = suser_sname(suser_sid()) OR 
  6012.                          is_srvrolemember('sysadmin') = 1 OR
  6013.                          is_member ('db_owner') = 1)     
  6014.         END
  6015.         FETCH hChelpsubscription_pub INTO @subscriber, @publication, 
  6016.             @destination_db, @pubid, @srvid, @immediate_sync
  6017.     END
  6018.  
  6019.     CLOSE hChelpsubscription_pub
  6020.     DEALLOCATE hChelpsubscription_pub
  6021.  
  6022.     CREATE TABLE #dist_agent_properties
  6023.     (
  6024.         job_id                    VARBINARY(16) NOT NULL,
  6025.         offload_enabled            bit NULL,
  6026.         offload_server            sysname collate database_default null,
  6027.         dts_package_name        sysname collate database_default null,
  6028.         dts_package_location    int NULL,
  6029.         status                    int NULL  
  6030.     )
  6031.  
  6032.     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  6033.                                            @distribdb = @distributiondb OUTPUT
  6034.     IF @retcode <> 0
  6035.         RETURN @retcode
  6036.  
  6037.     SELECT @distributor = RTRIM(@distributor)
  6038.  
  6039.     -- Get distribution agent properties 
  6040.     IF LOWER(@@SERVERNAME) <> LOWER(@distributor)
  6041.     BEGIN
  6042.         SELECT @distproc = @distributor + '.' + @distributiondb + 
  6043.                            '.dbo.sp_MSenumdistributionagentproperties'
  6044.     END    
  6045.     ELSE
  6046.     BEGIN
  6047.         SELECT @distproc = @distributiondb + 
  6048.                            '.dbo.sp_MSenumdistributionagentproperties'
  6049.     END
  6050.  
  6051.     SELECT @dbname = db_name()
  6052.  
  6053.     INSERT INTO #dist_agent_properties
  6054.       EXEC @retcode = @distproc @publisher = @@SERVERNAME, 
  6055.                                 @publisher_db =@dbname, 
  6056.                                 @publication = @orig_publication            
  6057.  
  6058.     /*
  6059.     ** Get subscriptions
  6060.     */
  6061.     SELECT 'subscriber'           = hs.subscriber,
  6062.            'publication'          = hs.publication,
  6063.            'article'              = hs.article,
  6064.            'destination database' = hs.destination_db,
  6065.            'subscription status'  = case
  6066.                 -- distributionstatus = 0 means that the subscription has been deactivated.  
  6067.                 when hs.status = 2 and ap.status = 0 then 0
  6068.                 else hs.status
  6069.                 end,
  6070.            'synchronization type' = hs.sync_type,
  6071.            'subscription type'    = hs.subscription_type,
  6072.            'full subscription'    = hs.full_subscription,
  6073.            'subscription_name'      = hs.subscription_name,
  6074.               -- SyncTran
  6075.            'update mode'          = hs.update_mode,
  6076.            'distribution job id' = hs.distribution_jobid,
  6077.            'loopback_detection'  = hs.loopback_detection,
  6078.            'offload_enabled'     = ap.offload_enabled,
  6079.            'offload_server'      = ap.offload_server,
  6080.            'dts_package_name'    = ap.dts_package_name,
  6081.            'dts_package_location' = ap.dts_package_location
  6082.       FROM #helpsubscription hs
  6083.       LEFT OUTER JOIN #dist_agent_properties ap
  6084.       ON hs.distribution_jobid = ap.job_id  
  6085.       ORDER BY subscriber, publication, article
  6086.  
  6087.     DROP TABLE #dist_agent_properties
  6088. go
  6089.  
  6090. EXEC dbo.sp_MS_marksystemobject sp_helpsubscription
  6091. GO
  6092.  
  6093. print ''
  6094. print 'Creating procedure sp_articlefilter'
  6095. go
  6096. create procedure sp_articlefilter (
  6097.     @publication sysname,           /* publication name */
  6098.     @article sysname,             /* article name */
  6099.     @filter_name nvarchar (386) = NULL,     /* name of filter procedure*/
  6100.     @filter_clause ntext = NULL,               /* article's filter clause */
  6101.     @force_invalidate_snapshot bit = 0,    /* Force invalidate existing snapshot */
  6102.     @force_reinit_subscription bit = 0    /* Force reinit subscription */
  6103. )
  6104. as
  6105. BEGIN
  6106.     declare @pubid smallint
  6107.             ,@table_name sysname
  6108.             ,@user_name sysname
  6109.             ,@qualified_table_name nvarchar (258)
  6110.             ,@filter_id int
  6111.             ,@type tinyint        
  6112.             ,@previous_proc nvarchar(386)
  6113.             ,@retcode int
  6114.             ,@site sysname
  6115.             ,@db sysname
  6116.             ,@owner sysname
  6117.             ,@object nvarchar(386)
  6118.             ,@artid int
  6119.             ,@active tinyint
  6120.             ,@obid int
  6121.             ,@view_id int
  6122.             ,@cmd nvarchar(4000)
  6123.             ,@allow_sync_tran bit
  6124.             ,@allow_queued_tran bit
  6125.  
  6126.     select @active = 2
  6127.  
  6128.     /*
  6129.     ** Security Check.
  6130.     */
  6131.     exec @retcode = dbo.sp_MSreplcheck_publish
  6132.     if @@ERROR <> 0 or @retcode <> 0
  6133.         return(1)
  6134.  
  6135.     /*
  6136.     ** Parameter Check:  @publication.
  6137.     ** Make sure that the publication exists and that it conforms to the
  6138.     ** rules for identifiers.
  6139.     */
  6140.     if @publication is null
  6141.            begin
  6142.               RAISERROR (14043, 16, -1, '@publication')
  6143.               return (1)
  6144.            END
  6145.     
  6146.     execute @retcode = dbo.sp_validname @publication
  6147.     if @retcode <> 0
  6148.     RETURN (1)
  6149.  
  6150.     select @pubid = pubid
  6151.         ,@allow_sync_tran = allow_sync_tran
  6152.         ,@allow_queued_tran = allow_queued_tran
  6153.     from syspublications where name = @publication
  6154.  
  6155.         if @pubid is null
  6156.            begin
  6157.             RAISERROR (20026, 11, -1, @publication)
  6158.             return (1)
  6159.            end
  6160.  
  6161.     /*
  6162.     ** Parameter Check:  @article.
  6163.     ** Check to make sure that the article exists in the publication.
  6164.     */
  6165.  
  6166.     if @article is null
  6167.        begin
  6168.               RAISERROR (14043, 16, -1, '@article')
  6169.               return (1)
  6170.            end
  6171.         /*
  6172.         execute @retcode = dbo.sp_validname @article
  6173.         if @retcode <> 0
  6174.        return (1)
  6175.        */
  6176.  
  6177.     /*
  6178.     ** Get the article information.
  6179.     */
  6180.     select @artid = art.artid, @table_name = so.name, @type = art.type,
  6181.        @filter_id = art.filter, @user_name = USER_NAME(so.uid)
  6182.         ,@view_id = ISNULL(art.sync_objid, art.objid)
  6183.        from sysarticles art, sysobjects so
  6184.        where art.pubid = @pubid
  6185.        and art.name = @article
  6186.        and art.objid = so.id
  6187.  
  6188.     /*
  6189.     ** Fail if there is no article information.
  6190.     */
  6191.     if @artid is null
  6192.        begin
  6193.               RAISERROR (20027, 11, -1, @article)
  6194.               return (1)
  6195.        end
  6196.  
  6197.         /*
  6198.         ** Error out if this is a not a table based article
  6199.         */
  6200.         IF NOT EXISTS ( SELECT * FROM sysarticles WHERE artid = @artid
  6201.                           AND pubid = @pubid
  6202.                           AND (type & 1) = 1 )
  6203.         BEGIN
  6204.             RAISERROR (14112, 11, -1 )
  6205.             RETURN (1)
  6206.         END
  6207.  
  6208.  
  6209.  
  6210.     /*
  6211.     ** Make sure a valid @filter_name was provided and it is
  6212.     ** a valid name.
  6213.     */
  6214.     if datalength(@filter_clause) > 0  
  6215.     begin
  6216.  
  6217.         /*
  6218.         ** Make sure a valid @filter_name was provided and it is
  6219.         ** a valid name.
  6220.         */
  6221.  
  6222.         if @filter_name is null
  6223.         begin
  6224.            RAISERROR (14043, 16, -1, '@filter_name')
  6225.            return (1)
  6226.         end
  6227.         
  6228.         select @object = PARSENAME( @filter_name, 1 )
  6229.         select @owner  = PARSENAME( @filter_name, 2 )
  6230.         select @db     = PARSENAME( @filter_name, 3 )
  6231.         select @site   = PARSENAME( @filter_name, 4 )
  6232.  
  6233.          if @object IS NULL
  6234.                return 1
  6235.  
  6236.         if @owner is NULL
  6237.             select @owner = user_name()
  6238.         select @object = quotename(@owner) + N'.' + quotename(@object)
  6239.     end
  6240.  
  6241.     -- Check if there are snapshot or subscriptions and raiserror if needed.
  6242.     EXECUTE @retcode  = dbo.sp_MSreinit_article
  6243.         @publication = @publication, 
  6244.         @article = @article,
  6245.         @need_new_snapshot = 1,
  6246.         @need_reinit_subscription = 1
  6247.         ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  6248.         ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  6249.         ,@check_only = 1
  6250.     IF @@ERROR <> 0 OR @retcode <> 0
  6251.         return 1
  6252.  
  6253.     begin tran
  6254.     save TRANSACTION articlefilter
  6255.  
  6256.     /*
  6257.     ** If the article has a generated filter (not manually created), then
  6258.     ** drop the current filter before creating the new one.
  6259.     */
  6260.     if ((@type & 0x3) <> 0x3) and @filter_id <> 0
  6261.        begin
  6262.           if exists (select * from sysobjects where id = @filter_id
  6263.                 and type = 'RF')
  6264.          begin
  6265.             exec dbo.sp_MSget_qualified_name @filter_id, @previous_proc output
  6266.             exec ('drop procedure ' + @previous_proc)
  6267.             if @@error <> 0
  6268.                goto UNDO
  6269.          end
  6270.  
  6271.        end
  6272.  
  6273.  
  6274.     /*
  6275.     ** make an owner qualified table name for these operations name
  6276.     */
  6277.  
  6278.     select @qualified_table_name = quotename(@user_name) + '.' + quotename(@table_name)
  6279.  
  6280.     -- Drop replication filter if it exists.
  6281.     -- Note: upgrade needs this logic
  6282.     if datalength(@filter_clause) > 0
  6283.         and exists (select * from sysobjects where id = object_id(@object)
  6284.                 and type = 'RF')
  6285.     begin
  6286.           exec ('drop procedure ' + @object)
  6287.         if @@error <> 0
  6288.            goto UNDO
  6289.     end
  6290.  
  6291.  
  6292.     /*
  6293.     ** If there is a @filter_clause, create the new filter and
  6294.     ** update the article filter id and filter_clause.
  6295.     **/
  6296.     if datalength(@filter_clause) > 0
  6297.        begin
  6298.         declare @subst_clause nvarchar(4000)
  6299.         select @subst_clause = @filter_clause
  6300.  
  6301.         exec @retcode = sp_MSsubst_filter_names @user_name, @table_name, @subst_clause output
  6302.         if @retcode <> 0 or @@error <> 0
  6303.             goto UNDO
  6304.         exec ('create procedure ' + @object +
  6305.             ' for replication as ' +
  6306.             'if exists (select * from ' + @qualified_table_name +
  6307.             ' where ' + @subst_clause +
  6308.             ') return 1 else return 0')
  6309.         if @@error <> 0
  6310.            goto UNDO
  6311.  
  6312.         if (@user_name in ('dbo','INFORMATION_SCHEMA'))
  6313.         begin
  6314.             exec @retcode = dbo.sp_MS_marksystemobject @object
  6315.             if @@error <> 0 
  6316.                 goto UNDO
  6317.         end
  6318.  
  6319.         select @filter_id = id  from sysobjects where id = object_id(@object)
  6320.             and type = 'RF'
  6321.         if @filter_id is null or @filter_id = 0
  6322.            begin
  6323.               RAISERROR (15001, 11, -1, @object)
  6324.               goto UNDO
  6325.            end
  6326.  
  6327.         /*
  6328.         ** Update article
  6329.         */
  6330.         update sysarticles set filter = @filter_id,
  6331.            filter_clause = @filter_clause
  6332.            where pubid = @pubid
  6333.               and name = @article
  6334.         if @@error <> 0
  6335.             goto UNDO
  6336.  
  6337.        -------------------------------------------------------------
  6338.        -- SQL SERVER 7.0 ONLY: update sysobjects, set parent id = underlying
  6339.        -- object id
  6340.        -------------------------------------------------------------
  6341.  
  6342.         select @obid = object_id( @qualified_table_name )
  6343.         EXEC @retcode = dbo.sp_MSsetfilterparent @object, @obid
  6344.         if @retcode <> 0 or @@error <> 0
  6345.             goto UNDO
  6346.         EXEC @retcode = dbo.sp_MSsetfilteredstatus @obid
  6347.         if @retcode <> 0 or @@error <> 0
  6348.             goto UNDO
  6349.  
  6350.        end
  6351.     else
  6352.     BEGIN
  6353.         /*
  6354.         ** Clear the filter id and filter_clause.
  6355.         */
  6356.         update sysarticles set filter = 0,
  6357.            filter_clause = NULL
  6358.            where pubid = @pubid
  6359.               and name = @article
  6360.         if @@error <> 0
  6361.             goto UNDO
  6362.  
  6363.         ---------------------------------------------------
  6364.         -- SQL SERVER 7.0 ONLY:  remove parent_id from filter proc
  6365.         ---------------------------------------------------
  6366.  
  6367.         select @obid = object_id( @qualified_table_name )
  6368.         if exists ( select * from sysobjects where name = @object
  6369.                 and type = 'RF')
  6370.         begin
  6371.             EXEC @retcode = dbo.sp_MSsetfilterparent @object, 0
  6372.             if @retcode <> 0 or @@error <> 0
  6373.                 goto UNDO
  6374.         end
  6375.         EXEC @retcode = dbo.sp_MSsetfilteredstatus @obid
  6376.         if @retcode <> 0 or @@error <> 0
  6377.             goto UNDO
  6378.     END
  6379.  
  6380.     -- Have to call this stored procedure to invalidate existing snapshot or reint
  6381.     -- subscriptions if needed
  6382.     EXECUTE @retcode  = dbo.sp_MSreinit_article
  6383.         @publication = @publication, 
  6384.         @article = @article,
  6385.         @need_new_snapshot = 1,
  6386.         @need_reinit_subscription = 1
  6387.         ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  6388.         ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  6389.     IF @@ERROR <> 0 OR @retcode <> 0
  6390.         GOTO UNDO
  6391.  
  6392.     /*
  6393.     ** Force the article cache to be refreshed with the new definition.
  6394.     */
  6395.     EXECUTE dbo.sp_replflush
  6396.     COMMIT TRANSACTION
  6397.     return 0
  6398. UNDO:
  6399.     if @@trancount > 0
  6400.     begin
  6401.         ROLLBACK TRANSACTION articlefilter
  6402.         commit tran
  6403.     end
  6404.     RETURN (1)
  6405. END
  6406. go
  6407.  
  6408. dump tran master with no_log
  6409. go
  6410.  
  6411. EXEC dbo.sp_MS_marksystemobject sp_articlefilter
  6412. GO
  6413.  
  6414. create procedure sp_MSscript_article_view 
  6415. @artid int,
  6416. @view_name sysname, 
  6417. @include_timestamps bit
  6418. as
  6419. declare @base_objid int
  6420. declare @columns varbinary(32)
  6421. declare @user_name sysname
  6422. declare @table_name sysname
  6423. declare @qualified_table_name nvarchar(520)
  6424. declare @filter_clause nvarchar(4000)
  6425.  
  6426. declare @cmdfrag nvarchar(4000)
  6427. declare @separator nvarchar(1)
  6428. declare @colname sysname
  6429.  
  6430. declare @retcode int
  6431.  
  6432. select @table_name = so.name,
  6433.        @base_objid = art.objid,
  6434.        @columns = art.columns,
  6435.        @user_name = USER_NAME(so.uid),
  6436.        @table_name = so.name,
  6437.        @qualified_table_name = QUOTENAME(USER_NAME(so.uid)) + '.' + QUOTENAME(so.name),
  6438.        @filter_clause = art.filter_clause
  6439.        from sysarticles art, sysobjects so
  6440.        where art.artid = @artid
  6441.        and art.objid = so.id
  6442.  
  6443. create table #tempcmd( c1 int identity NOT NULL, cmdfrag nvarchar(4000) collate database_default )
  6444.  
  6445. insert into #tempcmd (cmdfrag) values ( N'create view ' + QUOTENAME(@view_name) + N'as select ' )
  6446.  
  6447. create table #tmp (colid int NOT NULL primary key, name sysname collate database_default not null, published bit NOT NULL)
  6448.  
  6449. insert into #tmp select colid, name,
  6450.     convert(bit, convert( varbinary, substring( convert( nvarchar(16), @columns ), 16 - floor((colid-1)/16),1 )) & power( 2, ((colid-1)%16)))
  6451.     from syscolumns
  6452.     where id = @base_objid
  6453.  
  6454. if 1 = @include_timestamps
  6455. begin
  6456.     update #tmp set published = 1 where colid = (select colid from syscolumns c
  6457.         where c.id = @base_objid and c.xtype = 189)
  6458. end
  6459.  
  6460. declare hc  CURSOR LOCAL FAST_FORWARD FOR select name from #tmp
  6461.     where published = 1 order by colid asc
  6462. open hc
  6463. fetch hc into @colname
  6464.  
  6465. select @cmdfrag = N''
  6466. select @separator = N''
  6467.  
  6468. while (@@fetch_status <> -1)
  6469. begin
  6470.     if datalength( @cmdfrag ) > 3500 
  6471.     begin
  6472.         insert into #tempcmd(cmdfrag) values (@cmdfrag)
  6473.         select @cmdfrag = N''
  6474.     end
  6475.     select @cmdfrag = @cmdfrag + @separator + quotename(@colname)
  6476.  
  6477.     select @separator = N','
  6478.     fetch hc into @colname
  6479. end            
  6480. close hc
  6481. deallocate hc
  6482.  
  6483. insert into #tempcmd( cmdfrag ) values (@cmdfrag) 
  6484.  
  6485. insert into #tempcmd( cmdfrag ) values (N' from ')
  6486. insert into #tempcmd( cmdfrag ) values (@qualified_table_name)
  6487.  
  6488.  
  6489. insert into #tempcmd( cmdfrag ) values (N' where permissions(' + 
  6490.     convert(nvarchar(10), @base_objid)  + ') & 1 = 1 ')
  6491.  
  6492. if( @filter_clause is not null and datalength( @filter_clause ) > 0 )
  6493. begin
  6494.     exec @retcode = sp_MSsubst_filter_names @user_name, @table_name, @filter_clause output
  6495.     if @retcode <> 0 or @@error <> 0
  6496.         return 1        
  6497.     insert into #tempcmd( cmdfrag ) values ('and (' + @filter_clause + ')')
  6498. end
  6499.  
  6500. select cmdfrag from #tempcmd order by c1 asc
  6501.  
  6502. return 0
  6503. go
  6504.  
  6505. EXEC dbo.sp_MS_marksystemobject sp_MSscript_article_view 
  6506. GO
  6507.  
  6508.  
  6509. print ''
  6510. print 'Creating procedure sp_articleview'
  6511. go
  6512. create procedure sp_articleview (
  6513.     @publication sysname,        /* Publication name */
  6514.     @article sysname,          /* Article name */
  6515.     @view_name nvarchar (386) = NULL,  /* View name */
  6516.     @filter_clause ntext = NULL            /* Article's filter clause */
  6517.     ,@change_active int = 0
  6518.     ,@force_invalidate_snapshot bit = 0    /* Force invalidate existing snapshot */
  6519.     ,@force_reinit_subscription bit = 0    /* Force reinit subscription */
  6520. )
  6521. as
  6522. BEGIN
  6523.     declare @pubid smallint
  6524.             ,@table_name sysname
  6525.             ,@user_id int
  6526.             ,@user_name sysname
  6527.             ,@columns varbinary (32)
  6528.             ,@name sysname
  6529.             ,@retcode int
  6530.             ,@view_id int
  6531.             ,@type tinyint
  6532.             ,@table_id int
  6533.             ,@previous_view sysname
  6534.             ,@quoted_prev_view sysname
  6535.             ,@colid int
  6536.             ,@object sysname
  6537.             ,@quoted_object nvarchar(512)
  6538.             ,@artid int
  6539.             ,@active tinyint
  6540.             ,@allow_sync_tran bit
  6541.             ,@allow_queued_tran bit
  6542.             ,@filter_id int
  6543.  
  6544.     select @active = 2
  6545.  
  6546.     /*
  6547.     ** Security Check.
  6548.     */
  6549.     exec @retcode = dbo.sp_MSreplcheck_publish
  6550.     if @@ERROR <> 0 or @retcode <> 0
  6551.         return(1)
  6552.  
  6553.     /*
  6554.     ** Parameter Check:  @publication.
  6555.     ** Make sure that the publication exists and that it conforms to the
  6556.     ** rules for identifiers.
  6557.     */
  6558.     if @publication is null
  6559.            begin
  6560.               RAISERROR (14043, 16, -1, '@publication')
  6561.               return (1)
  6562.            END
  6563.  
  6564.     execute @retcode = dbo.sp_validname @publication
  6565.     if @retcode <> 0
  6566.             RETURN (1)
  6567.  
  6568.     select @pubid = pubid
  6569.         ,@allow_sync_tran = allow_sync_tran
  6570.         ,@allow_queued_tran = allow_queued_tran        
  6571.     from syspublications where name = @publication
  6572.     if @pubid is null
  6573.     begin
  6574.         RAISERROR (20026, 11, -1, @publication)
  6575.         return (1)
  6576.     end
  6577.  
  6578.     /*
  6579.     ** Parameter Check:  @article.
  6580.     ** Check to make sure that the article exists in the publication.
  6581.     */
  6582.  
  6583.     if @article is null
  6584.        begin
  6585.               RAISERROR (14043, 16, -1, '@article')
  6586.               return (1)
  6587.            end
  6588.     
  6589.     /*
  6590.         execute @retcode = dbo.sp_validname @article
  6591.         if @retcode <> 0
  6592.        return (1)
  6593.        */
  6594.  
  6595.     /*
  6596.     ** Get the article information.
  6597.     */
  6598.     declare @status tinyint
  6599.     declare @objid int
  6600.     select @artid = art.artid, @table_name = so.name,
  6601.        @user_id = uid, @user_name = USER_NAME(so.uid),
  6602.        @columns = art.columns, @type = art.type,
  6603.        @status = art.status,
  6604.        @objid = art.objid,
  6605.        @view_id = art.sync_objid, @table_id = art.objid
  6606.         ,@type = art.type
  6607.         ,@filter_id = art.filter
  6608.        from sysarticles art, sysobjects so
  6609.        where art.pubid = @pubid
  6610.        and art.name = @article
  6611.        and art.objid = so.id
  6612.  
  6613.     /*
  6614.     ** Fail if there is no article information.
  6615.     */
  6616.     if @artid is null
  6617.        begin
  6618.               RAISERROR (20027, 11, -1, @article)
  6619.               return (1)
  6620.        end
  6621.  
  6622.         /*
  6623.         ** Error out if this is a not a table based article
  6624.         */
  6625.         IF NOT EXISTS ( SELECT * FROM sysarticles WHERE artid = @artid
  6626.                           AND pubid = @pubid
  6627.                           AND (type & 1) = 1 )
  6628.             BEGIN
  6629.                 RAISERROR (14112, 11, -1 )
  6630.                 RETURN (1)
  6631.             END
  6632.    
  6633.     
  6634.     -- Special handling for timestamp column for queued publication.
  6635.     -- Although timestamp values are not needed, they have to be presented in bcp files. Otherwise
  6636.     -- bcp in will fail with data file format error.
  6637.  
  6638.     declare @include_timestamps bit
  6639.     select @include_timestamps = 0
  6640.     
  6641.     if @allow_queued_tran = 1 and @status & 32 <> 0
  6642.     begin
  6643.         select @include_timestamps = 1
  6644.     end
  6645.     
  6646.     /* Break out the specified view name and get the non-ownerqual'd name, then validate that. */
  6647.     select @object = PARSENAME( @view_name, 1 )
  6648.  
  6649.     if @object IS NULL
  6650.     begin
  6651.         -- generate view name
  6652.         declare @viewname varchar(255)
  6653.         declare @guid uniqueidentifier
  6654.         set @guid = CONVERT(varbinary(16), LEFT(NEWID(),8))
  6655.         exec @retcode = master.dbo.xp_varbintohexstr @guid, @viewname OUTPUT
  6656.         if @@ERROR <> 0 OR @retcode <> 0
  6657.             return (1)
  6658.         set @viewname = 'syncobj_' + @viewname
  6659.         set @object = @viewname
  6660.     end
  6661.  
  6662.  
  6663.     select @quoted_object = QUOTENAME(@object)
  6664.  
  6665.     execute @retcode = dbo.sp_validname @object
  6666.     if @retcode <> 0
  6667.         return (1)
  6668.  
  6669.     -- Check if there are snapshot or subscriptions and raiserror if needed.
  6670.     EXECUTE @retcode  = dbo.sp_MSreinit_article
  6671.         @publication = @publication, 
  6672.         @article = @article,
  6673.         @need_new_snapshot = 1,
  6674.         @need_reinit_subscription = 1
  6675.         ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  6676.         ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  6677.         ,@check_only = 1
  6678.     IF @@ERROR <> 0 OR @retcode <> 0
  6679.         return 1
  6680.  
  6681. CreateView:
  6682.     begin tran
  6683.     save TRANSACTION articleview
  6684.  
  6685.     /*
  6686.     ** If the article has a generated view (not manually created), then
  6687.     ** drop the current view before creating the new one.
  6688.     */
  6689.     if ((@type & 0x5) <> 0x5) and @view_id <> 0
  6690.             and @view_id <> @table_id
  6691.     begin
  6692.         select @previous_view = object_name (@view_id)
  6693.         if @previous_view is not null and
  6694.                 exists (select * from sysobjects where name = @previous_view
  6695.                 and type = 'V')
  6696.         begin
  6697.             select @quoted_prev_view = QUOTENAME(@previous_view)
  6698.             exec ('drop view ' + @quoted_prev_view)
  6699.             if @@error <> 0
  6700.                 goto UNDO
  6701.         end
  6702.     end
  6703.  
  6704.     /*
  6705.     ** Construct and execute the view creation command.
  6706.     */
  6707.     -- Drop the existing view.
  6708.     -- Note: upgrade needs this logic
  6709.     if datalength(@filter_clause) > 0 and
  6710.         exists (select * from sysobjects where id = object_id(@object)
  6711.     and type = 'V') 
  6712.     begin
  6713.         exec ('drop view ' + @quoted_object)
  6714.         if @@error <> 0
  6715.             goto UNDO
  6716.     end
  6717.  
  6718.     ---------------------------------------------
  6719.     --  Update article definition 
  6720.     --  Set @filter_clause value
  6721.     ---------------------------------------------
  6722.  
  6723.     if datalength(@filter_clause) > 0
  6724.     begin
  6725.        update sysarticles set filter_clause = @filter_clause
  6726.           where pubid = @pubid
  6727.           and name = @article
  6728.         if @@error <> 0
  6729.             goto UNDO
  6730.     end
  6731.     else
  6732.     begin
  6733.        update sysarticles set filter_clause = NULL
  6734.           where pubid = @pubid
  6735.           and name = @article
  6736.         if @@error <> 0
  6737.             goto UNDO
  6738.     end
  6739.  
  6740.  
  6741.     -----------------------------------------------------------
  6742.     -- create the view
  6743.     -----------------------------------------------------------
  6744.  
  6745.     declare @cmd nvarchar(2000)
  6746.     declare @dbname sysname
  6747.  
  6748.     select @cmd = N'exec sp_MSscript_article_view ' + cast(@artid as nvarchar(20)) 
  6749.                 + N',N' + quotename(@object,'''') +  
  6750.                 + N',' + cast(@include_timestamps as nvarchar(1))
  6751.     select @dbname = db_name()
  6752.     
  6753.     exec @retcode = master..xp_execresultset @cmd, @dbname
  6754.     if @@error <> 0 or @retcode <> 0
  6755.         goto UNDO
  6756.  
  6757.     -----------------------------------------------------------
  6758.     -- grant the permission of the view to public so that non
  6759.     -- db_owner can do validation.
  6760.     -----------------------------------------------------------
  6761.     select @cmd = 'grant select on ' + QUOTENAME(@object) + ' to public'
  6762.     exec (@cmd)
  6763.     if @@error <> 0
  6764.         goto UNDO
  6765.  
  6766.  
  6767.     -----------------------------------------------------------
  6768.     -- Update the article's sync_objid with the new view id
  6769.     -----------------------------------------------------------
  6770.  
  6771.     select @view_id = id from sysobjects where name = @object and type = 'V'
  6772.     if @view_id is null or @view_id = 0
  6773.     begin
  6774.         RAISERROR (15001, 11, -1, @object)
  6775.         goto UNDO
  6776.     end
  6777.     else
  6778.     begin
  6779.         if (@user_name in ('dbo','INFORMATION_SCHEMA'))
  6780.             EXEC dbo.sp_MS_marksystemobject @object
  6781.     end
  6782.  
  6783.     ---------------------------------------------
  6784.     --  Update article definition 
  6785.     --  Set new sync_objid 
  6786.     ---------------------------------------------
  6787.  
  6788.     update sysarticles set sync_objid = @view_id
  6789.       where pubid = @pubid
  6790.       and name = @article
  6791.     if @@error <> 0 
  6792.         goto UNDO
  6793.  
  6794.     -- sp_repldropcolumn used @change_active = 2 to prepare, don't invalidate or reinitialize
  6795.     if @change_active <> 2
  6796.     begin
  6797.         -- Have to call this stored procedure to invalidate existing snapshot or reint
  6798.         -- subscriptions if needed
  6799.         EXECUTE @retcode  = dbo.sp_MSreinit_article
  6800.             @publication = @publication, 
  6801.             @article = @article,
  6802.             @need_new_snapshot = 1,
  6803.             @need_reinit_subscription = 1
  6804.             ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  6805.             ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  6806.         IF @@ERROR <> 0 OR @retcode <> 0
  6807.             GOTO UNDO
  6808.     end
  6809.  
  6810.     /*
  6811.     ** Force the article cache to be refreshed with the new definition.
  6812.     */
  6813.     EXECUTE dbo.sp_replflush
  6814.     COMMIT TRANSACTION
  6815.  
  6816.     --
  6817.     -- Validate that the new view does not exclude the horizontal filter
  6818.     --
  6819.     if ((@allow_sync_tran = 1 or @allow_queued_tran = 1) and
  6820.         (datalength(@filter_clause) > 0))
  6821.     begin
  6822.         select @cmd = N'select top 0 * into #dummy from ' + 
  6823.             quotename(@user_name) + N'.' + quotename(object_name(@view_id)) +
  6824.             N' where ' + cast(@filter_clause as nvarchar(4000))
  6825.         exec (@cmd)
  6826.         if (@@error != 0)
  6827.         begin
  6828.             --
  6829.             -- The row filter does not work for the current view
  6830.             --
  6831.             declare @h_filter nvarchar(4000)
  6832.             select @h_filter = cast(@filter_clause as nvarchar(4000))
  6833.             raiserror(21392, 16, 1, @h_filter, @object, @article, @publication)
  6834.             
  6835.             --
  6836.             -- drop the filter if not manually generated 
  6837.             --
  6838.             if ((@type & 0x3) <> 0x3) and @filter_id <> 0
  6839.             begin
  6840.                 if exists (select * from sysobjects where id = @filter_id and type = 'RF')
  6841.                 begin
  6842.                     declare @filter_proc nvarchar(386)
  6843.                     exec dbo.sp_MSget_qualified_name @filter_id, @filter_proc output
  6844.                     exec ('drop procedure ' + @filter_proc)
  6845.  
  6846.                     update dbo.sysarticles set filter = 0, filter_clause = NULL
  6847.                         where pubid = @pubid and name = @article
  6848.  
  6849.                     raiserror(21393, 16, 1, @h_filter, @article, @publication)
  6850.                 end
  6851.             end
  6852.             return 1
  6853.         end
  6854.     end
  6855.  
  6856.     return 0
  6857. UNDO:
  6858.     if @@trancount > 0
  6859.     begin
  6860.         ROLLBACK TRANSACTION articleview
  6861.         commit tran
  6862.     end
  6863.     RETURN (1)
  6864. END
  6865. go
  6866.  
  6867. EXEC dbo.sp_MS_marksystemobject sp_articleview
  6868. GO
  6869.  
  6870. dump tran master with no_log
  6871. go
  6872.  
  6873. print ''
  6874. print 'Creating procedure sp_MSaddexearticle'
  6875. go
  6876. CREATE PROCEDURE sp_MSaddexecarticle
  6877.     @publication sysname,               /* publication name */
  6878.     @article     sysname,             /* article name */
  6879.     @source_proc nvarchar (92),                 /* table name */
  6880.     @destination_proc sysname = NULL,           /* destination table name */
  6881.     @type sysname = NULL,                       /* article type */
  6882.     @creation_script nvarchar (127) = NULL,           /* article schema script */
  6883.     @description nvarchar (255) = NULL,                 /* article description */
  6884.     @pre_creation_cmd nvarchar(10) = 'drop',           /* 'none', 'drop', 'delete', 'truncate' */
  6885.     @schema_option binary(8) = NULL,    /* script out stored procedure */
  6886.     @destination_owner sysname,
  6887.     @article_id int OUTPUT
  6888.  
  6889.     AS
  6890.  
  6891.  
  6892.     SET NOCOUNT ON
  6893.  
  6894.     /* variables for SP_NAMECRACK */
  6895.  
  6896.     DECLARE @site sysname
  6897.     DECLARE @db sysname
  6898.     DECLARE @owner sysname
  6899.     DECLARE @object sysname
  6900.  
  6901.     DECLARE @retcode   int
  6902.  
  6903.     DECLARE @procid    int
  6904.     DECLARE @procnum   smallint
  6905.     DECLARE @pubid     int
  6906.     DECLARE @precmdid  int
  6907.  
  6908.     DECLARE @typeid      smallint
  6909.     DECLARE @publish_bit smallint
  6910.     DECLARE @incompatible_typeid smallint
  6911.  
  6912.     DECLARE @cmd nvarchar(255)
  6913.     DECLARE @sysobj_colname  sysname
  6914.  
  6915.     SELECT  @typeid      = 24
  6916.  
  6917.  
  6918.     SELECT @sysobj_colname = 'replinfo'
  6919.     SELECT @publish_bit = 1
  6920.  
  6921.  
  6922.     /*
  6923.     ** Parameter Check: @article.
  6924.     ** The @article name cannot be NULL and must conform to the rules
  6925.     ** for identifiers.
  6926.     */
  6927.  
  6928.     IF @article IS NULL
  6929.         BEGIN
  6930.             RAISERROR (14043, 16, -1, '@article')
  6931.             RETURN (1)
  6932.         END
  6933.     
  6934.     /*
  6935.     EXECUTE @retcode = dbo.sp_validname @article
  6936.  
  6937.     IF @retcode <> 0
  6938.     return(1)
  6939.     */
  6940.  
  6941.     if LOWER(@article) = 'all'
  6942.         BEGIN
  6943.             RAISERROR (14032, 16, -1, '@article')
  6944.             RETURN (1)
  6945.         END
  6946.  
  6947.     /*
  6948.     ** Parameter Check: @publication.
  6949.     ** The @publication name cannot be NULL and must conform to the rules
  6950.     ** for identifiers.
  6951.     */
  6952.  
  6953.     IF @publication IS NULL
  6954.         BEGIN
  6955.             RAISERROR (14043, 16, -1, '@publication')
  6956.             RETURN (1)
  6957.         END
  6958.  
  6959.     EXECUTE @retcode = dbo.sp_validname @publication
  6960.  
  6961.     IF @retcode <> 0
  6962.     RETURN (1)
  6963.  
  6964.     /*
  6965.     ** Parameter Check: @source_proc.
  6966.     ** Check to see that the @source_proc is local, that it conforms
  6967.     ** to the rules for identifiers, and that it is a procedure
  6968.     */
  6969.  
  6970.     IF @source_proc IS NULL
  6971.     BEGIN
  6972.         RAISERROR (14043, 16, -1, '@source_proc')
  6973.         RETURN (1)
  6974.     END
  6975.  
  6976.    select @object = PARSENAME( @source_proc, 1 )
  6977.    select @owner  = PARSENAME( @source_proc, 2 )
  6978.    select @db     = PARSENAME( @source_proc, 3 )
  6979.    select @site   = PARSENAME( @source_proc, 4 )
  6980.  
  6981.    if @object IS NULL
  6982.          return 1
  6983.  
  6984.  
  6985.     IF @source_proc LIKE '%.%.%' AND @db <> DB_NAME()
  6986.     BEGIN
  6987.         RAISERROR (14004, 16, -1, @source_proc)
  6988.         RETURN (1)
  6989.     END
  6990.     
  6991.  
  6992.     /*
  6993.     **  Get the id of the @source_proc
  6994.     */
  6995.  
  6996.     SELECT @procid = id
  6997.       FROM sysobjects
  6998.      WHERE id = OBJECT_ID(@source_proc)
  6999.      AND   type = 'P'
  7000.  
  7001.     IF @procid IS NULL
  7002.     BEGIN
  7003.         RAISERROR (14027, 11, -1, @source_proc)
  7004.         RETURN (1)
  7005.     END
  7006.  
  7007.     /*
  7008.     ** Parameter Check:  @destination_proc.
  7009.     ** If the destination proc is not specified, assume it's the same
  7010.     ** as the source. 
  7011.     */
  7012.     
  7013.     IF @destination_proc IS NULL
  7014.     BEGIN
  7015.         -- Perform parsing only if the destination_proc parameter is not provided
  7016.         SELECT @destination_proc = @source_proc
  7017.  
  7018.         select @object = PARSENAME( @destination_proc, 1 )
  7019.         select @owner  = PARSENAME( @destination_proc, 2 )
  7020.         select @db     = PARSENAME( @destination_proc, 3 )
  7021.         select @site   = PARSENAME( @destination_proc, 4 )
  7022.  
  7023.         if @object IS NULL
  7024.              return 1 
  7025.     END
  7026.  
  7027.     /*
  7028.     ** Get the pubid.
  7029.     */
  7030.  
  7031.     SELECT @pubid = pubid FROM syspublications WHERE name = @publication
  7032.  
  7033.     IF @pubid IS NULL
  7034.         BEGIN
  7035.             RAISERROR (14027, 11, -1, @publication)
  7036.             RETURN (1)
  7037.         END
  7038.  
  7039.     /*
  7040.     ** Parameter Check:  @article, @publication.
  7041.     ** Check if the article already exists in this publication.
  7042.     */
  7043.  
  7044.     IF EXISTS (SELECT *
  7045.                  FROM sysextendedarticlesview
  7046.                 WHERE pubid = @pubid
  7047.                   AND name = @article)
  7048.         BEGIN
  7049.             RAISERROR (14030, 16, -1, @article, @publication)
  7050.             RETURN (1)
  7051.         END
  7052.  
  7053.  
  7054.     /*
  7055.     ** Set the precmdid.  The default type is 'drop'.
  7056.     **
  7057.     **      @precmdid   pre_creation_cmd
  7058.     **      =========   ================
  7059.     **            0     none
  7060.     **          1     drop
  7061.     */
  7062.     IF LOWER(@pre_creation_cmd) NOT IN ('none', 'drop')
  7063.        BEGIN
  7064.           RAISERROR (14111, 16, -1)
  7065.           RETURN (1)
  7066.        END
  7067.  
  7068.     /*
  7069.     ** Determine the integer value for the pre_creation_cmd.
  7070.     */
  7071.  
  7072.     IF LOWER(@pre_creation_cmd) = 'none'
  7073.        SELECT @precmdid = 0
  7074.     ELSE IF LOWER(@pre_creation_cmd) = 'drop'
  7075.        SELECT @precmdid = 1
  7076.  
  7077.     /*  Determine 'type' value for article.
  7078.     **
  7079.     **            8     proc exec
  7080.     **           24     serializable proc exec
  7081.     */
  7082.  
  7083.     IF @type IS NULL
  7084.     BEGIN
  7085.         SELECT @type = 'serializable proc exec'
  7086.     END
  7087.     ELSE IF LOWER(@type) NOT IN ('proc exec', 'serializable proc exec')
  7088.     BEGIN
  7089.             RAISERROR (14118, 16, -1)
  7090.             RETURN (1)
  7091.     END
  7092.  
  7093.     IF LOWER(@type) = 'proc exec'
  7094.     BEGIN
  7095.        SELECT @typeid = 8
  7096.        SELECT @incompatible_typeid = 24
  7097.     END
  7098.     ELSE IF LOWER(@type) = 'serializable proc exec'
  7099.     BEGIN
  7100.        SELECT @typeid = 24
  7101.        SELECT @incompatible_typeid = 8
  7102.     END
  7103.  
  7104.     -- make sure we haven't already created an article of a different type
  7105.     -- on this proc
  7106.  
  7107.     IF EXISTS ( select * from sysobjects where id = @procid
  7108.                 and replinfo & @incompatible_typeid = @incompatible_typeid )
  7109.     BEGIN
  7110.        RAISERROR (21024, 16, -1, @source_proc )
  7111.        RETURN(1)
  7112.     END
  7113.  
  7114.     /*
  7115.     ** Parameter Check:  @creation_script and @schema_option
  7116.     ** @schema_option is null, set the default value
  7117.     */
  7118.     IF @schema_option IS NULL
  7119.     BEGIN
  7120.         SELECT @schema_option = 1
  7121.     /* 
  7122.         RAISERROR (14043, 16, -1, '@schema_option')
  7123.         RETURN (1)
  7124.         */
  7125.     END
  7126.  
  7127.     IF @schema_option <> 0x0000000000000000 AND 
  7128.        @schema_option <> 0x0000000000000001 AND
  7129.        @schema_option <> 0x0000000000002000 AND
  7130.        @schema_option <> 0x0000000000002001  
  7131.     BEGIN
  7132.         RAISERROR (20014, 10, -1)
  7133.         RETURN (1)
  7134.     END
  7135.  
  7136.     /*
  7137.     **  Add article to sysarticles and update sysobjects category bit.
  7138.     */
  7139.  
  7140.     begin tran
  7141.     save TRAN sp_MSaddexecarticle
  7142.         INSERT sysarticles (columns, creation_script, del_cmd, description,
  7143.                             dest_table, filter, filter_clause, ins_cmd, name,
  7144.                 objid, pre_creation_cmd, pubid,
  7145.                             status, sync_objid, type, upd_cmd, schema_option,
  7146.                             dest_owner)
  7147.         VALUES (0, @creation_script, NULL, @description,
  7148.                 @destination_proc, 0, '', NULL, @article,
  7149.                 @procid, @precmdid, @pubid,
  7150.                 0, @procid, @typeid, NULL, @schema_option,
  7151.                 @destination_owner)
  7152.  
  7153.         IF @@ERROR <> 0
  7154.         BEGIN
  7155.             if @@trancount > 0
  7156.             begin
  7157.                 ROLLBACK TRAN sp_MSaddexecarticle
  7158.                 commit tran
  7159.             end
  7160.             RETURN (1)
  7161.         END
  7162.  
  7163.         SELECT @article_id = @@IDENTITY
  7164.  
  7165.         select @cmd = 'UPDATE sysobjects SET ' + @sysobj_colname
  7166.         select @cmd = @cmd + ' = ' + @sysobj_colname + ' | ' + CONVERT( nvarchar, @publish_bit )
  7167.         select @cmd = @cmd + ' WHERE id = (SELECT objid FROM sysarticles WHERE name = '''
  7168.         select @cmd = @cmd + @article + ''' and pubid = ' + CONVERT( nvarchar, @pubid ) + ')'
  7169.  
  7170.         EXEC (@cmd)
  7171.  
  7172.         IF @@ERROR <> 0
  7173.         BEGIN
  7174.             if @@trancount > 0
  7175.             begin
  7176.                 ROLLBACK TRAN sp_MSaddexecarticle
  7177.                 commit tran
  7178.             end
  7179.             RETURN (1)
  7180.         END
  7181.  
  7182.  
  7183.     COMMIT TRAN
  7184. go
  7185.  
  7186. EXEC dbo.sp_MS_marksystemobject sp_MSaddexecarticle
  7187. GO
  7188.  
  7189. print ''
  7190. print 'Creating procedure sp_MSaddschemaarticle'
  7191. go
  7192.  
  7193. CREATE PROCEDURE sp_MSaddschemaarticle
  7194.     @publication        sysname,        /* Name of the publciation */
  7195.     @article            sysname,        /* Name of the article */
  7196.     @source_object      sysname,        /* Name of object to be replicated */
  7197.     @destination_object sysname,        /* Name of the object created on the subscriber */
  7198.     @type               tinyint,        /* Must be one of 0x20, 0x40, or 0x80 */
  7199.     @creation_script    nvarchar(255),  /* custom creation script for the article */
  7200.     @description        nvarchar(255),  /* article description */
  7201.     @pre_creation_cmd   nvarchar(10),   /* must be 'none' or 'drop' */
  7202.     @schema_option      binary(8),
  7203.     @destination_owner  sysname,        /* owner of the article object on the subscriber */
  7204.     @status             tinyint, 
  7205.     @artid              int OUTPUT
  7206. AS
  7207.     SET NOCOUNT ON
  7208.     DECLARE @retcode int
  7209.         
  7210.     DECLARE @source_owner           sysname
  7211.     DECLARE @object                 sysname
  7212.     DECLARE @bInTran                bit
  7213.     DECLARE @pubid                  int
  7214.     DECLARE @source_objid           int
  7215.     DECLARE @pre_creation_cmdid     tinyint
  7216.     
  7217.     /* Variables for setting up RPC call to the Distributor */
  7218.     DECLARE @distproc               nvarchar(2000)
  7219.     DECLARE @distributor            sysname
  7220.     DECLARE @distributiondb         sysname
  7221.     DECLARE @dbname                 sysname
  7222.     DECLARE @valid_schema_options   int
  7223.     
  7224.     SELECT @bInTran = 0
  7225.  
  7226.     SELECT @source_owner = PARSENAME(@source_object, 2)
  7227.     SELECT @object = PARSENAME(@source_object, 1)
  7228.  
  7229.     /* Note that @article & @publication has been by sp_addarticle 
  7230.        as non-null */
  7231.         
  7232.     /*
  7233.     ** Get the pubid of the publication
  7234.     */
  7235.     SELECT @pubid = NULL
  7236.     SELECT @pubid = pubid
  7237.       FROM syspublications
  7238.      WHERE name = @publication
  7239.  
  7240.     IF @pubid IS NULL
  7241.     BEGIN
  7242.         RAISERROR (14027, 11, -1, @publication)
  7243.         RETURN (1)
  7244.     END
  7245.  
  7246.     /*
  7247.     ** Get the source object id
  7248.     */
  7249.     SELECT @source_objid = NULL
  7250.     SELECT @source_objid = OBJECT_ID(@source_object)    
  7251.  
  7252.     /*
  7253.     **  Destination object name
  7254.     */
  7255.     IF @destination_object IS NULL
  7256.         SELECT @destination_object = @source_object
  7257.  
  7258.     /*
  7259.     ** Parameter check: @type
  7260.     ** @type must correspond to the object type of the source object
  7261.     **
  7262.     ** @type = 0x20 => source object type = 'P'
  7263.     ** @type = 0x40 => source object type = 'V'
  7264.     ** @type = 0x80 => source object type = 'FN' OR 'TF' OR 'IF'
  7265.     */
  7266.     IF @type = 0x20
  7267.     BEGIN
  7268.         IF NOT EXISTS (SELECT *
  7269.                          FROM sysobjects
  7270.                         WHERE id = @source_objid
  7271.                           AND xtype = 'P ')
  7272.         BEGIN
  7273.             RAISERROR(21219, 16, -1)
  7274.             RETURN (1)
  7275.         END
  7276.     END
  7277.     ELSE IF @type = 0x40
  7278.     BEGIN
  7279.         IF NOT EXISTS (SELECT *
  7280.                          FROM sysobjects 
  7281.                         WHERE id = @source_objid
  7282.                           AND xtype = 'V ')
  7283.         BEGIN
  7284.             RAISERROR(21221, 16, -1)
  7285.             RETURN (1)
  7286.         END
  7287.     END   
  7288.     ELSE IF @type = 0x80
  7289.     BEGIN
  7290.         IF NOT EXISTS (SELECT *
  7291.                          FROM sysobjects 
  7292.                         WHERE id = @source_objid
  7293.                           AND (xtype in ('FN','TF','IF')))
  7294.         BEGIN
  7295.             RAISERROR(21228, 16, -1)            
  7296.             RETURN (1)
  7297.         END
  7298.     END
  7299.  
  7300.  
  7301.     /*
  7302.     ** Parameter check: @schema_option
  7303.     ** @schema_option can only contain the bits 0x0000000000000001 and
  7304.     ** 0x0000000000002000
  7305.     ** for schema only articles except view. View articles can contain 
  7306.     ** the options 0x0000000000000010, 0x0000000000000020, and 
  7307.     ** 0x0000000000000100 in addition to the aforementioned options.
  7308.     */
  7309.     IF @type = 0x40
  7310.     BEGIN
  7311.  
  7312.         -- Since only the lower 32 bits of @schema_option are
  7313.         -- currently used, the following check is sufficient.
  7314.         -- Note that @schema_option should have been padded out by now
  7315.         DECLARE @schema_option_lodword int
  7316.         SELECT @valid_schema_options = 0x2151
  7317.         SELECT @schema_option_lodword = fn_replgetbinary8lodword(@schema_option)
  7318.         IF (@schema_option_lodword & ~@valid_schema_options) <> 0
  7319.         BEGIN
  7320.             RAISERROR (21229, 16, -1)
  7321.             RETURN (1)
  7322.         END
  7323.     END
  7324.     ELSE IF @schema_option NOT IN (0x0000000000000000,
  7325.                                    0x0000000000000001,
  7326.                                    0x0000000000002000,
  7327.                                    0x0000000000002001)
  7328.     BEGIN
  7329.         RAISERROR (21222, 16, -1)
  7330.         RETURN (1)
  7331.     END 
  7332.     
  7333.     /*
  7334.     ** Parameter check: @pre_creation_command must be
  7335.     ** 'drop' (id = 1) or 'none' (id = 0)
  7336.     */
  7337.     SELECT @pre_creation_cmd = LOWER(@pre_creation_cmd)
  7338.     IF @pre_creation_cmd NOT IN (N'none', N'drop')
  7339.     BEGIN
  7340.         RAISERROR(21223, 16, -1)
  7341.         RETURN (1)
  7342.     END
  7343.     
  7344.     IF @pre_creation_cmd = N'none'
  7345.         SELECT @pre_creation_cmdid = 0
  7346.     ELSE IF @pre_creation_cmd = N'drop'
  7347.         SELECT @pre_creation_cmdid = 1
  7348.     
  7349.     /*
  7350.     ** Parameter Check:  @article, @publication.
  7351.     ** Check if the article already exists in this publication.
  7352.     */
  7353.  
  7354.     IF EXISTS (SELECT *
  7355.                  FROM sysextendedarticlesview
  7356.                 WHERE pubid = @pubid
  7357.                   AND name = @article)
  7358.         BEGIN
  7359.             RAISERROR (14030, 16, -1, @article, @publication)
  7360.             RETURN (1)
  7361.         END
  7362.  
  7363.     BEGIN TRANSACTION sp_MSaddschemaarticle
  7364.     SAVE TRANSACTION sp_MSaddschemaarticle
  7365.     SELECT @bInTran = 1    
  7366.  
  7367.     -- Add a dummy record to sysarticles to reserve an artid
  7368.     INSERT sysarticles (dest_table, filter, name, objid, pubid, 
  7369.                         pre_creation_cmd, status, sync_objid, type)  
  7370.     VALUES (@destination_object, N'', @article, @source_objid, @pubid,
  7371.             @pre_creation_cmdid, @status, @source_objid, @type)
  7372.  
  7373.     IF @@ERROR <> 0
  7374.         GOTO Failure
  7375.  
  7376.     SELECT @artid = @@IDENTITY   
  7377.  
  7378.     -- Now that we have reserved an artid in sysarticles,
  7379.     -- we can remove the dummy record
  7380.     
  7381.     DELETE sysarticles WHERE artid = @artid AND pubid = @pubid
  7382.  
  7383.     IF @@ERROR <> 0
  7384.         GOTO Failure
  7385.  
  7386.     -- Insert a record into sysschemaarticles to represent this
  7387.     -- schema only article
  7388.     INSERT sysschemaarticles 
  7389.     VALUES (@artid, @creation_script, @description, @destination_object,
  7390.             @article, @source_objid, @pubid, @pre_creation_cmdid, @status,
  7391.             @type, @schema_option, @destination_owner)
  7392.  
  7393.     IF @@ERROR <> 0
  7394.         GOTO Failure
  7395.  
  7396.     -- Make a bit in replinfo to prevent the source object from
  7397.     -- being dropped
  7398.     UPDATE sysobjects SET replinfo = replinfo | 0x00000200 WHERE id = @source_objid
  7399.     
  7400.     IF @@ERROR <> 0
  7401.         GOTO Failure       
  7402.  
  7403.     COMMIT TRANSACTION  
  7404.  
  7405.     RETURN (0)
  7406. Failure:
  7407.  
  7408.     IF @bInTran = 1
  7409.     BEGIN
  7410.         ROLLBACK TRANSACTION sp_MSaddschemaarticle
  7411.         COMMIT TRANSACTION
  7412.     END
  7413.     RETURN (1)
  7414. go
  7415.  
  7416. EXEC dbo.sp_MS_marksystemobject sp_MSaddschemaarticle
  7417. GO
  7418.  
  7419. print ''
  7420. print 'Creating procedure sp_addarticle'
  7421. go
  7422. CREATE PROCEDURE sp_addarticle
  7423.     @publication        sysname,                /* publication name */
  7424.     @article            sysname,                /* article name */
  7425.     @source_table       nvarchar (386) = NULL,  /* table name */
  7426.     @destination_table  sysname = NULL,            /* destination table name */
  7427.     @vertical_partition nchar(5) = 'false',     /* vertical partition */
  7428.     @type               sysname = NULL,            /* article type */
  7429.     @filter                nvarchar (386) = NULL,  /* stored procedure used to filter table */
  7430.     @sync_object        nvarchar (386) = NULL,  /* view or table used for synchronization */
  7431.     @ins_cmd            nvarchar (255) = NULL,  /* insert format string */
  7432.     @del_cmd            nvarchar (255) = NULL,  /* delete format string */
  7433.     @upd_cmd            nvarchar (255) = NULL,  /* update format string */
  7434.     @creation_script    nvarchar (127) = NULL,  /* article schema script */
  7435.     @description        nvarchar (255) = NULL,  /* article description */
  7436.     @pre_creation_cmd   nvarchar(10) = 'drop',  /* 'none', 'drop', 'delete', 'truncate' */
  7437.     @filter_clause      ntext    = NULL,        /* where clause */
  7438.     @schema_option      varbinary(8) = NULL,
  7439.     @destination_owner  sysname = NULL,
  7440.     @status                tinyint = 16,           /* Default: binary command format */
  7441.     @source_owner       sysname = NULL,         /* NULL for 6.5 users, not NULL for 7.0 users */
  7442.     @sync_object_owner  sysname = NULL,         /* NULL for 6.5 users, not NULL for 7.0 users */
  7443.     @filter_owner       sysname = NULL,            /* NULL for 6.5 users, not NULL for 7.0 users */
  7444.     @source_object      sysname = NULL,            /* if @source_table is NULL, this parameter can not be NULL */
  7445.     @artid              int = NULL OUTPUT,       /* article id of the new article  */
  7446.     @auto_identity_range    nvarchar(5)    = 'FALSE',    /* set it to false for now - change is possible */
  7447.     @pub_identity_range        bigint    = NULL,
  7448.     @identity_range            bigint = NULL,
  7449.     @threshold                int    = NULL,
  7450.     @force_invalidate_snapshot bit = 0    /* Force invalidate existing snapshot */
  7451.     AS
  7452.  
  7453.     SET NOCOUNT ON
  7454.  
  7455.     /*
  7456.     ** Declarations.
  7457.     */    
  7458.     DECLARE @bak_source sysname
  7459.     DECLARE @num_columns int
  7460.     DECLARE @accessid smallint
  7461.     DECLARE @db sysname
  7462.     DECLARE @filterid int
  7463.     DECLARE @object sysname
  7464.     DECLARE @owner sysname
  7465.     DECLARE @pubid int
  7466.     DECLARE @publish_bit smallint
  7467.     DECLARE @retcode int
  7468.     DECLARE @site sysname
  7469.     DECLARE @syncid int
  7470.     DECLARE @tabid int
  7471.     DECLARE @typeid smallint
  7472.     DECLARE @pkkey sysname
  7473.     DECLARE @i int
  7474.     DECLARE @indid int
  7475.     DECLARE @precmdid int
  7476.     DECLARE @object_type nchar(2)
  7477.     DECLARE @push tinyint
  7478.     DECLARE @dbname sysname
  7479.     DECLARE @cmd nvarchar(255)
  7480.     DECLARE @fHasPk int
  7481.     DECLARE @no_sync tinyint
  7482.     DECLARE @immediate_sync bit
  7483.     DECLARE @is_filter_in_use int
  7484.     DECLARE @distributor sysname
  7485.     DECLARE @distribdb sysname
  7486.     DECLARE @distproc nvarchar (255)
  7487.     DECLARE @sync_method tinyint
  7488.     -- SyncTran
  7489.     DECLARE @autogen_sync_procs_id int
  7490.     DECLARE @custom_proc_name nvarchar(255)
  7491.     DECLARE @guid varbinary(16)
  7492.     declare @allow_sync_tran bit
  7493.     DECLARE @repl_freq int
  7494.     declare @allow_queued_tran bit
  7495.     declare @allow_dts bit
  7496.     declare @merge_pub_object_bit  int
  7497.     declare @valid_ins_cmd nvarchar(255)
  7498.             ,@valid_upd_cmd nvarchar(255)
  7499.             ,@valid_del_cmd nvarchar(255)
  7500.             ,@MSrepl_tran_version_datatype sysname
  7501.             ,@colid int
  7502.     declare @backward_comp_level int
  7503.     declare @schema_option_int int
  7504.     select @backward_comp_level = 10 -- default to sphinx
  7505.     
  7506.     select @merge_pub_object_bit     = 128
  7507.     SELECT @push = 0
  7508.     SELECT @dbname = DB_NAME()
  7509.  
  7510.     SELECT @publish_bit = 1
  7511.  
  7512.     SELECT @no_sync = 2 /* no sync type in syssubscriptions */
  7513.     /*
  7514.     ** Security Check.
  7515.     */
  7516.     exec @retcode = dbo.sp_MSreplcheck_publish
  7517.     if @@ERROR <> 0 or @retcode <> 0
  7518.         return(1)
  7519.  
  7520.     /*
  7521.     ** Padding out the specified schema option to the left
  7522.     */
  7523.     select @schema_option = fn_replprepadbinary8(@schema_option)
  7524.  
  7525.     /*
  7526.     ** Parameter Check: @article.
  7527.     ** The @article name cannot be NULL and must conform to the rules
  7528.     ** for identifiers.
  7529.     */
  7530.  
  7531.     IF @article IS NULL
  7532.         BEGIN
  7533.             RAISERROR (14043, 16, -1, '@article')
  7534.             RETURN (1)
  7535.         END
  7536.  
  7537.     exec @retcode = dbo.sp_MSreplcheck_name @article
  7538.     if @@ERROR <> 0 or @retcode <> 0
  7539.         return(1)
  7540.  
  7541.     if LOWER(@article) = 'all'
  7542.         BEGIN
  7543.             RAISERROR (14032, 16, -1, '@article')
  7544.             RETURN (1)
  7545.         END
  7546.  
  7547.     /*
  7548.     ** Parameter Check: @publication.
  7549.     ** The @publication name cannot be NULL and must conform to the rules
  7550.     ** for identifiers.
  7551.     */
  7552.  
  7553.     IF @publication IS NULL
  7554.     BEGIN
  7555.         RAISERROR (14043, 16, -1, '@publication')
  7556.         RETURN (1)
  7557.     END
  7558.  
  7559.     EXECUTE @retcode = dbo.sp_validname @publication
  7560.  
  7561.     IF @retcode <> 0
  7562.     RETURN (1)
  7563.  
  7564.     /*
  7565.     ** Parameter Check: @destination_owner.
  7566.     ** The @destination_owner must conform to the rules
  7567.     ** for identifiers.
  7568.     */
  7569.  
  7570.     if @destination_owner is not null
  7571.     BEGIN
  7572.         EXECUTE @retcode = dbo.sp_validname @destination_owner
  7573.  
  7574.         IF @retcode <> 0
  7575.             RETURN (1)
  7576.     END
  7577.  
  7578.     /*
  7579.     ** Parameter Check: @source_table.
  7580.     ** Check to see that the @source_table is local, that it conforms
  7581.     ** to the rules for identifiers, and that it is a table, and not
  7582.     ** a view or another database object.
  7583.     */
  7584.  
  7585.     IF @source_table IS NULL
  7586.         BEGIN
  7587.             if @source_object is NOT NULL
  7588.                 select @source_table = @source_object
  7589.             else
  7590.                 begin
  7591.                     RAISERROR (14043, 16, -1, '@source_table')
  7592.                     RETURN (1)
  7593.                 end
  7594.         END
  7595.  
  7596.     IF @source_owner is NULL -- 6.5 users only
  7597.     begin
  7598.         IF @source_table LIKE '%.%.%' AND PARSENAME(@source_table, 3) <> DB_NAME()
  7599.                BEGIN
  7600.                   RAISERROR (14004, 16, -1, @source_table)
  7601.                   RETURN (1)
  7602.                END
  7603.     end
  7604.  
  7605.     -- For 7.0 users, @source_owner is not nullable.
  7606.     
  7607.     select @bak_source = @source_table
  7608.     
  7609.     IF @source_owner is not NULL
  7610.         begin
  7611.             select @source_table = QUOTENAME(@source_owner) + '.' + QUOTENAME(@source_table)
  7612.             IF @destination_table IS NULL
  7613.                 SELECT @destination_table = @bak_source
  7614.         end
  7615.     ELSE 
  7616.     begin
  7617.         -- Make @source_table qualifed.
  7618.         select @tabid = object_id(@source_table)
  7619.         if @tabid is not null
  7620.         begin
  7621.             exec @retcode = dbo.sp_MSget_qualified_name @tabid, @source_table output
  7622.             if @retcode <> 0 or @@error <> 0
  7623.                 return 1    
  7624.             IF @destination_table IS NULL
  7625.             -- Set destination_table if not provided or default by now.
  7626.             -- If @source_table is qualified (6.x behavior) only use table name for destination name.
  7627.                 SELECT @destination_table = PARSENAME(@source_table, 1)    
  7628.         end
  7629.     end
  7630.         
  7631.     select @num_columns=count(*) from syscolumns where id = object_id(@source_table)
  7632.     if @num_columns > 255
  7633.         begin
  7634.             RAISERROR (20068, 16, -1, @source_table, 255)
  7635.             RETURN (1)
  7636.         end
  7637.  
  7638.     /*
  7639.     **  Get the id of the @source_table
  7640.     */
  7641.     SELECT @tabid = id, @object_type = type
  7642.     FROM sysobjects
  7643.     WHERE id = OBJECT_ID(@source_table)
  7644.  
  7645.     IF @tabid IS NULL
  7646.         BEGIN
  7647.             RAISERROR (14027, 11, -1, @source_table)
  7648.             RETURN (1)
  7649.         END
  7650.  
  7651.     /*
  7652.     ** Parameter Check: @type
  7653.     ** If the article is added as a 'schema-bound view schema only' article,
  7654.     ** make sure that the source object is a schema-bound view.
  7655.     ** Conversely, a schema-bound view cannot be published as a 
  7656.     ** 'view schema only' article.
  7657.     */
  7658.     IF @type IS NULL
  7659.         SELECT @type = 'logbased'
  7660.  
  7661.     select @type = lower(@type)
  7662.  
  7663.     if @type = N'indexed view schema only' and objectproperty(@tabid, 'IsSchemaBound') <> 1
  7664.     begin
  7665.         raiserror (21277, 11, -1, @source_table)        
  7666.         return (1)    
  7667.     end
  7668.  
  7669.     /*
  7670.     ** If the article is published as an IV logbased article, we'd better make
  7671.     ** sure that the view is schema bound and it has a clustered index.
  7672.     ** Conversely, a schema-bound view should never be published as a regular
  7673.     ** table logbased article.
  7674.     */
  7675.     if @type in (N'indexed view logbased', 
  7676.                  N'indexed view logbased manualfilter', 
  7677.                  N'indexed view logbased manualview', 
  7678.                  N'indexed view logbased manualboth') and 
  7679.             objectproperty(@tabid, 'IsSchemaBound') <> 1 and
  7680.         not exists (select * from sysindexes where id = @tabid)
  7681.     begin
  7682.         raiserror (21278, 11, -1, @source_table)
  7683.         return (1)
  7684.     end    
  7685.     
  7686.     if @type in (N'view schema only', 
  7687.                  N'logbased', 
  7688.                  N'logbased manualfilter', 
  7689.                  N'logbased manualview', 
  7690.                  N'logbased manualboth') and 
  7691.         objectproperty(@tabid, 'IsSchemaBound') = 1
  7692.     begin
  7693.         raiserror (21275, 11, -1, @source_table)
  7694.         return (1)
  7695.     end
  7696.  
  7697.     -- Check if there are snapshot or subscriptions and raiserror if needed.
  7698.     EXECUTE @retcode  = dbo.sp_MSreinit_article
  7699.         @publication = @publication, 
  7700.         -- Virtual subscriptions of all the articles will be deactivated.
  7701.         -- @article = @article,
  7702.         @need_new_snapshot = 1,
  7703.         @force_invalidate_snapshot = @force_invalidate_snapshot,
  7704.         @check_only = 1
  7705.     IF @@ERROR <> 0 OR @retcode <> 0
  7706.         return 1
  7707.  
  7708.  
  7709.     -- Encrypted objects are not publishable for replication
  7710.     IF @type IN (N'proc exec',
  7711.                  N'serializable proc exec',
  7712.                  N'proc schema only',
  7713.                  N'indexed view schema only',
  7714.                  N'indexed view logbased',
  7715.                  N'indexed view logbased manualfilter',
  7716.                  N'indexed view logbased manualview',
  7717.                  N'indexed view logbased manualboth',
  7718.                  N'view schema only',
  7719.                  N'func schema only')
  7720.     BEGIN
  7721.         IF EXISTS (SELECT * FROM syscomments
  7722.                     WHERE id = @tabid
  7723.                       AND encrypted = 1)
  7724.         BEGIN
  7725.             RAISERROR(21004, 16, -1, @source_table)        
  7726.             RETURN (1)
  7727.         END
  7728.     END   
  7729.  
  7730.     -- at this point, we've done all the common parameter checks.
  7731.     -- If this is a procedure execution article, branch to the proc execution publishing
  7732.     -- routine; or if this is a schema only procedure or view article, brach to the
  7733.     -- schema only article publishing routine; otherwise continue processing as if it were a table
  7734.  
  7735.     IF (@object_type = 'P' AND @type <> N'proc schema only') or 
  7736.         @type IN (N'proc schema only', N'view schema only', N'func schema only', 'indexed view schema only')
  7737.     BEGIN
  7738.         begin tran
  7739.         save TRAN sp_addarticle
  7740.  
  7741.         IF (@object_type = 'P' AND @type <> N'proc schema only')
  7742.         begin
  7743.  
  7744.             IF @schema_option IS NULL
  7745.             BEGIN
  7746.                 SELECT @schema_option = 0x0000000000000001
  7747.             END
  7748.  
  7749.             EXECUTE @retcode = dbo.sp_MSaddexecarticle @publication,
  7750.                 @article,
  7751.                 @source_table,
  7752.                 @destination_table,
  7753.                 @type,
  7754.                 @creation_script,
  7755.                 @description,
  7756.                 @pre_creation_cmd,
  7757.                 @schema_option,
  7758.                 @destination_owner,
  7759.                 @artid OUTPUT
  7760.         end
  7761.         else 
  7762.         begin
  7763.             -- Note: a transaction is started inside sp_MSaddschemaarticle        
  7764.             IF @schema_option IS NULL
  7765.             BEGIN
  7766.                 SELECT @schema_option = 0x0000000000000001
  7767.             END
  7768.  
  7769.             IF @type = N'proc schema only'
  7770.             BEGIN
  7771.                 SELECT @typeid = 0x20
  7772.             END
  7773.             ELSE IF @type = N'view schema only'
  7774.             BEGIN
  7775.                 SELECT @typeid = 0x40
  7776.             END    
  7777.             ELSE IF @type = N'func schema only'
  7778.             BEGIN
  7779.                 SELECT @typeid = 0x80
  7780.             select @backward_comp_level = 40 -- UDF not available in sphinx
  7781.             END
  7782.             ELSE IF @type = N'indexed view schema only'
  7783.             BEGIN
  7784.                 SELECT @typeid = 0x40
  7785.             select @backward_comp_level = 40 -- SchemaBinding not available in sphinx
  7786.             END    
  7787.  
  7788.             EXECUTE @retcode = dbo.sp_MSaddschemaarticle 
  7789.                 @publication = @publication,
  7790.                 @article = @article,
  7791.                 @source_object = @source_table,
  7792.                 @destination_object = @destination_table,
  7793.                 @type = @typeid,
  7794.                 @creation_script = @creation_script,
  7795.                 @description = @description,
  7796.                 @pre_creation_cmd = @pre_creation_cmd,
  7797.                 @schema_option = @schema_option,
  7798.                 @destination_owner = @destination_owner,
  7799.                 @status = @status,
  7800.                 @artid = @artid OUTPUT
  7801.  
  7802.         end
  7803.         IF @retcode <> 0 or @@error <> 0
  7804.             goto UNDO
  7805.     end
  7806.     ELSE
  7807.     begin
  7808.  
  7809.         /*
  7810.         ** Make sure that the table name specified is a table and not a view.
  7811.         */
  7812.  
  7813.         IF NOT EXISTS (SELECT * FROM sysobjects
  7814.             WHERE id = (SELECT OBJECT_ID(@source_table))
  7815.             AND type = 'U')
  7816.             AND NOT EXISTS ( SELECT * FROM sysobjects so, sysindexes si
  7817.             WHERE so.id = OBJECT_ID(@source_table)
  7818.             AND so.type = 'V'
  7819.             AND si.id = so.id )
  7820.         BEGIN
  7821.             RAISERROR (14028, 16, -1)
  7822.             RETURN (1)
  7823.         END
  7824.  
  7825.  
  7826.         /*
  7827.         ** Parameter Check:  @destination_table.
  7828.         ** If the destination table is not specified, assume it's the same
  7829.         ** as the source table.  Make sure that the table name is not qualified.
  7830.         */
  7831.  
  7832.         /*
  7833.         ** Parameter Check: @vertical_partition
  7834.         ** Check to make sure that the vertical partition is either TRUE or FALSE.
  7835.         */
  7836.  
  7837.         SELECT @vertical_partition = LOWER(@vertical_partition)
  7838.         IF @vertical_partition NOT IN ('true', 'false')
  7839.         BEGIN
  7840.             RAISERROR (14029, 16, -1)
  7841.             RETURN (1)
  7842.         END
  7843.  
  7844.         /*
  7845.         ** Parameter Check: @filter
  7846.         ** Make sure that the filter is a valid stored procedure.
  7847.         */
  7848.         IF @filter IS NOT NULL
  7849.         BEGIN
  7850.             IF @filter_owner IS NULL
  7851.             BEGIN
  7852.                 select @object = PARSENAME( @filter, 1 )
  7853.                 select @owner  = PARSENAME( @filter, 2 )
  7854.                 select @db     = PARSENAME( @filter, 3 )
  7855.                 select @site   = PARSENAME( @filter, 4 )
  7856.  
  7857.                 if @object IS NULL
  7858.                   return 1
  7859.             END  
  7860.             ELSE
  7861.             BEGIN
  7862.                 select @filter = QUOTENAME(@filter_owner) + '.' + QUOTENAME(@filter)
  7863.             END
  7864.  
  7865.             /*
  7866.             ** Get the id of the @filter
  7867.             */
  7868.             select @filterid = id from sysobjects where
  7869.                 id = OBJECT_ID(@filter) and type = 'RF'
  7870.             IF @filterid IS NULL
  7871.             BEGIN
  7872.                 RAISERROR (14027, 11, -1, @filter)
  7873.                 RETURN (1)
  7874.             END
  7875.  
  7876.             EXEC @is_filter_in_use = dbo.sp_MSdoesfilterhaveparent @filterid
  7877.             if( @is_filter_in_use <> 0 )
  7878.             BEGIN
  7879.                 RAISERROR( 21009, 11, -1 )
  7880.                 RETURN (1)
  7881.             END
  7882.         END
  7883.         ELSE
  7884.             select @filterid = 0
  7885.  
  7886.  
  7887.         /*
  7888.         ** Get the pubid and its properties
  7889.         */
  7890.         SELECT @pubid = pubid, @autogen_sync_procs_id = autogen_sync_procs, @sync_method = sync_method,
  7891.             @allow_sync_tran = allow_sync_tran,
  7892.             @allow_queued_tran = allow_queued_tran,
  7893.             @allow_dts    = allow_dts,
  7894.             @repl_freq = repl_freq 
  7895.         FROM syspublications where name = @publication
  7896.  
  7897.         IF @pubid IS NULL
  7898.             BEGIN
  7899.                 RAISERROR (14027, 11, -1, @publication)
  7900.                 RETURN (1)
  7901.             END
  7902.  
  7903.         -- Only allow table and index view for dts publications
  7904.         if @allow_dts <> 0 and @type not in ( 
  7905.             N'logbased', 
  7906.             N'logbased manualfilter', 
  7907.             N'logbased manualview', 
  7908.             N'logbased manualboth',
  7909.             N'indexed view logbased', 
  7910.             N'indexed view logbased manualfilter', 
  7911.             N'indexed view logbased manualview', 
  7912.             N'indexed view logbased manualboth')
  7913.         begin
  7914.             raiserror(20611, 16, -1)
  7915.             return(1)
  7916.         end
  7917.  
  7918.         -- can't do fancy type stuff with MVs!
  7919.  
  7920.         ELSE IF (@allow_sync_tran <> 0 
  7921.                 OR @allow_queued_tran <> 0)
  7922.                 AND EXISTS ( select * from sysobjects 
  7923.                     where id = OBJECT_ID(@source_table)
  7924.                     and xtype = 'V' )
  7925.         BEGIN
  7926.             RAISERROR(14059, 16, -1)
  7927.             RETURN 1
  7928.         END
  7929.         
  7930.         --
  7931.         -- parameter check: @status
  7932.         -- bits 8, 16, 64 can be set directly
  7933.         -- Other bits from 1 ~ 64 are used but cannot be set here.
  7934.         -- Bit 64 can only be set for publication that allows DTS.
  7935.         -- Bit 32 is set internally according to whether or not timestamp is in
  7936.         -- the partition for queued publications.
  7937.  
  7938.         IF (@status & ~ 88 ) <> 0 
  7939.         BEGIN
  7940.             RAISERROR( 21061, 16, -1, @status, @article )
  7941.             RETURN (1)
  7942.         END
  7943.         else if (@status & 64 <> 0 and @allow_dts = 0)
  7944.         begin
  7945.             raiserror(20590, 16, -1)
  7946.             return (1)
  7947.         end
  7948.  
  7949.  
  7950.         /*
  7951.         ** Parameter Check:  @article, @publication.
  7952.         ** Check if the article already exists in this publication.
  7953.         */
  7954.  
  7955.         IF EXISTS (SELECT *
  7956.                      FROM sysextendedarticlesview
  7957.                     WHERE pubid = @pubid
  7958.                       AND name = @article)
  7959.             BEGIN
  7960.                 RAISERROR (14030, 16, -1, @article, @publication)
  7961.                 RETURN (1)
  7962.             END
  7963.  
  7964.         /*
  7965.         ** Set the typeid.  The default type is logbased.  Anything else is
  7966.         ** currently undefined (reserved for future use).
  7967.         **
  7968.         **      @typeid     type
  7969.         **      =======     ========
  7970.         **          1     logbased
  7971.         **          3     logbased manualfilter
  7972.         **          5     logbased manualview
  7973.         **          7     logbased manualboth
  7974.         **          8     proc exec              (valid in dbo.sp_MSaddexecarticle)
  7975.         **          24    serializable proc exec (valid in dbo.sp_MSaddexecarticle)
  7976.         **          32    proc schema only       (valid in dbo.sp_MSaddschemaarticle)
  7977.         **          64    view schema only       (valid in dbo.sp_MSaddschemaarticle)
  7978.         **         128    func schema only       (valid in dbo.sp_MSaddschemaarticle)
  7979.         **       Note that for the following article types, the 256 bit is not really persisted
  7980.         **         257    indexed view logbased
  7981.         **         259    indexed view logbased manualfilter
  7982.         **         261    indexed view logbased manualview
  7983.         **         263    indexed view logbased manualboth
  7984.         **         320    indexed view schema only (valid in dbo.sp_MSaddschemaarticle)
  7985.         */
  7986.  
  7987.  
  7988.         IF LOWER(@type) NOT IN ('logbased', 
  7989.                                      'logbased manualfilter', 
  7990.                                      'logbased manualview', 
  7991.                                      'logbased manualboth',
  7992.                                      'indexed view logbased', 
  7993.                                      'indexed view logbased manualfilter', 
  7994.                                      'indexed view logbased manualview', 
  7995.                                      'indexed view logbased manualboth',
  7996.                                      'proc schema only', 
  7997.                                      'view schema only')
  7998.         BEGIN
  7999.             RAISERROR (14023, 16, -1)
  8000.             RETURN (1)
  8001.         END
  8002.  
  8003.         IF LOWER(@type) = 'logbased' OR LOWER(@type) = 'indexed view logbased'
  8004.             SELECT @typeid = 1
  8005.         ELSE IF LOWER(@type) = 'logbased manualfilter' OR LOWER(@type) = 'indexed view logbased manualfilter'
  8006.            SELECT @typeid = 3
  8007.         ELSE IF LOWER(@type) = 'logbased manualview' OR LOWER(@type) = 'indexed view logbased manualview'
  8008.            SELECT @typeid = 5
  8009.         ELSE IF LOWER(@type) = 'logbased manualboth' OR LOWER(@type) = 'indexed view logbased manualboth'
  8010.             SELECT @typeid = 7
  8011.  
  8012.         /*
  8013.         ** Set the precmdid.  The default type is 'drop'.
  8014.         **
  8015.         **      @precmdid   pre_creation_cmd
  8016.         **      =========   ================
  8017.         **            0     none
  8018.         **          1     drop
  8019.         **          2     delete
  8020.         **          3     truncate
  8021.         */
  8022.         IF LOWER(@pre_creation_cmd) NOT IN ('none', 'drop', 'delete', 'truncate')
  8023.         BEGIN
  8024.             RAISERROR (14061, 16, -1)
  8025.             RETURN (1)
  8026.         END
  8027.  
  8028.         /*
  8029.         ** Determine the integer value for the pre_creation_cmd.
  8030.         */
  8031.         IF LOWER(@pre_creation_cmd) = 'none'
  8032.             SELECT @precmdid = 0
  8033.         ELSE IF LOWER(@pre_creation_cmd) = 'drop'
  8034.             SELECT @precmdid = 1
  8035.         ELSE IF LOWER(@pre_creation_cmd) = 'delete'
  8036.             SELECT @precmdid = 2
  8037.         ELSE IF LOWER(@pre_creation_cmd) = 'truncate'
  8038.             SELECT @precmdid = 3
  8039.  
  8040.         IF @sync_object IS NULL
  8041.             select @syncid = @tabid
  8042.         ELSE
  8043.         BEGIN
  8044.  
  8045.         IF @sync_object_owner is NULL  -- 6.5 only
  8046.         BEGIN
  8047.  
  8048.             /*
  8049.             ** Parameter Check: @sync_object.
  8050.             ** Check to see that the sync_object is local and that it
  8051.             ** conforms to the rules for identifiers.
  8052.             */
  8053.  
  8054.             select @object = PARSENAME( @sync_object, 1 )
  8055.             select @owner  = PARSENAME(  @sync_object, 2 )
  8056.             select @db     = PARSENAME(  @sync_object, 3 )
  8057.             select @site   = PARSENAME(  @sync_object, 4 )
  8058.  
  8059.             if @object IS NULL
  8060.                   return 1
  8061.  
  8062.  
  8063.             IF @sync_object LIKE '%.%.%' AND @db <> DB_NAME()
  8064.             BEGIN
  8065.                 RAISERROR (14004, 16, -1, @sync_object)
  8066.                 RETURN (1)
  8067.             END
  8068.  
  8069.         END -- end of 65 processing
  8070.         else -- for sphinx, @sync_object_owner can not be null
  8071.             select @sync_object = QUOTENAME(@sync_object_owner) + '.' + QUOTENAME(@sync_object)
  8072.             
  8073.             /*
  8074.             **  Get the id of the @sync_object
  8075.             */
  8076.  
  8077.             SELECT @syncid = id FROM sysobjects WHERE id = OBJECT_ID(@sync_object)
  8078.  
  8079.             IF @syncid IS NULL
  8080.             BEGIN
  8081.                 RAISERROR (14027, 11, -1, @sync_object)
  8082.                 RETURN (1)
  8083.             END
  8084.  
  8085.             /*
  8086.             ** Make sure the sync object specified is a table or a view.
  8087.             */
  8088.  
  8089.             IF NOT EXISTS (SELECT * FROM sysobjects
  8090.                     WHERE id = (SELECT OBJECT_ID(@sync_object))
  8091.                     AND (type = 'U' or
  8092.                          type = 'V'))
  8093.             BEGIN
  8094.                 RAISERROR (14031, 16, -1)
  8095.                 RETURN (1)
  8096.             END
  8097.         END
  8098.  
  8099.         /*
  8100.         ** If the publication is log-based, or allows updating subscribers
  8101.         ** make sure there is a primary key on the source table.
  8102.         ** or a UCI on the view.
  8103.         ** NOTE!  sprok in SPSUP.SQL
  8104.         */
  8105.         IF EXISTS (SELECT * FROM syspublications 
  8106.             WHERE pubid = @pubid AND
  8107.                 (repl_freq = 0 OR allow_sync_tran = 1 OR @allow_queued_tran = 1))
  8108.         BEGIN
  8109.             EXEC @fHasPk = dbo.sp_MSreplsup_table_has_pk @tabid
  8110.  
  8111.             IF @fHasPk = 0
  8112.             BEGIN
  8113.                 IF EXISTS ( select * from sysobjects 
  8114.                     where id = OBJECT_ID(@source_table)
  8115.                     and xtype = 'U' )
  8116.                 BEGIN
  8117.                     RAISERROR (14088, 16, -1, @source_table)
  8118.                 END
  8119.                 ELSE
  8120.                 BEGIN
  8121.                     RAISERROR( 14089, 16, -1, @source_table)
  8122.                 END
  8123.                 RETURN (1)
  8124.             END
  8125.         END
  8126.  
  8127.         /*
  8128.         ** Parameter Check:  @creation_script and @schema_option
  8129.         ** @schema_option cannot be null
  8130.         ** If @schema_option is 0, there have to be @creation_script defined.
  8131.         */
  8132.         IF @schema_option IS NULL
  8133.         BEGIN
  8134.             -- Snapshot publication, no custom proc. generation
  8135.             -- We need insert proc for snapshot publications for DTS.
  8136.             -- Do not generate user triggers by default (0x00100 - user trigger flag)
  8137.             IF @repl_freq = 1 and @allow_dts = 0
  8138.             BEGIN
  8139.                 SELECT @schema_option  = 0x0000000000000071
  8140.             END
  8141.             ELSE
  8142.             BEGIN
  8143.                 SELECT @schema_option  = 0x00000000000000F3
  8144.             END
  8145.  
  8146.             if (@allow_queued_tran = 1)
  8147.                 select @schema_option = fn_replprepadbinary8(fn_replgetbinary8lodword(@schema_option) | 0x8000)
  8148.         END
  8149.  
  8150.         /*
  8151.         ** Parameter Check: @schema_option
  8152.         ** If bit 0x2 is set, this cannot be an article for a snapshot publication
  8153.         ** For queued updating, DRI_Primary Key option has to be set
  8154.         */
  8155.         IF ((CONVERT(INT, @schema_option) & 0x2) <> 0) AND (@repl_freq = 1)
  8156.         BEGIN
  8157.             RAISERROR (21143, 16, -1)
  8158.             RETURN (1)
  8159.         END
  8160.         else if ((@allow_queued_tran = 1) and 
  8161.             ((fn_replgetbinary8lodword(@schema_option) & 0x8000) = 0))
  8162.         BEGIN
  8163.             RAISERROR (21394, 16, 1)
  8164.             RETURN (1)
  8165.         END
  8166.         
  8167.         /* 
  8168.         ** Since custom proc name is based on destination table name
  8169.         */
  8170.         
  8171.         if @allow_dts = 0
  8172.             set @custom_proc_name = @destination_table
  8173.         else
  8174.             set @custom_proc_name = @article
  8175.  
  8176.         -- Publication allow dts/queued must use parameterized commands and 
  8177.         -- ins/upd/del commands are generated 
  8178.         -- internally and are fixed (they will used as keys to find the correct transformations)
  8179.         if (@allow_dts = 1 or @allow_queued_tran = 1)
  8180.         begin
  8181.             select @valid_ins_cmd = N'CALL sp_MSins_' + @custom_proc_name
  8182.             IF @repl_freq = 0
  8183.             begin
  8184.                 --
  8185.                 -- Note :
  8186.                 -- Now that we are autogenrating the custom procs for queued
  8187.                 -- we will follow the current behavior :
  8188.                 -- for queued INS/UPD/DEL will use CALL/XCALL/XCALL respectively
  8189.                 -- for DTS INS/UPD/DEL will use CALL/XCALL/XCALL
  8190.                 -- In case it allows both queued and DTS, DTS will take precedence
  8191.                 -- YWU: Check this
  8192.                 --
  8193.                 select @valid_del_cmd = N'XCALL sp_MSdel_' + @custom_proc_name
  8194.                 if (@allow_queued_tran = 1)
  8195.                 begin
  8196.                     select @valid_upd_cmd = N'XCALL sp_MSupd_' + @custom_proc_name
  8197.                 end
  8198.                 if (@allow_dts = 1)
  8199.                 begin
  8200.                     if @status = 16
  8201.                         select @valid_upd_cmd = N'CALL sp_MSupd_' + @custom_proc_name
  8202.                     else 
  8203.                         select @valid_upd_cmd = N'XCALL sp_MSXpd_' + @custom_proc_name
  8204.                 end
  8205.             end
  8206.             else
  8207.             begin
  8208.                 select @valid_upd_cmd = N'SQL'
  8209.                 select @valid_del_cmd = N'SQL'
  8210.             end
  8211.  
  8212.             if (@allow_dts = 1)
  8213.             begin
  8214.                 -- For publication allows DTS, @status can only be 16 or 48
  8215.                 -- 
  8216.                 if  (@status <> 16 and @status <> 80) or
  8217.                     (@ins_cmd is not null and @ins_cmd <> @valid_ins_cmd) or 
  8218.                     (@upd_cmd is not null and @upd_cmd <> @valid_upd_cmd) or 
  8219.                     (@del_cmd is not null and @del_cmd <> @valid_del_cmd)
  8220.                 begin
  8221.                     raiserror(21174, 16, -1)
  8222.                     return (1)
  8223.                 end
  8224.             end 
  8225.             else if (@allow_queued_tran = 1)
  8226.             begin
  8227.                 if  (@ins_cmd is not null and @ins_cmd != @valid_ins_cmd) or 
  8228.                     (@upd_cmd is not null and @upd_cmd != @valid_upd_cmd) or 
  8229.                     (@del_cmd is not null and @del_cmd != @valid_del_cmd)
  8230.                 begin
  8231.                     raiserror(21191, 16, -1, @valid_ins_cmd, @valid_upd_cmd, @valid_del_cmd)
  8232.                     return (1)
  8233.                 end
  8234.             end
  8235.                 
  8236.             select @ins_cmd = @valid_ins_cmd
  8237.             select @upd_cmd = @valid_upd_cmd
  8238.             select @del_cmd = @valid_del_cmd
  8239.         end
  8240.         -- If pub sync_type is character mode bcp(1) 
  8241.         else if @sync_method = 1
  8242.         begin
  8243.             -- Parameterized command is not supported. Mask it off.
  8244.             select @status = @status & ~16
  8245.             if @ins_cmd is NULL  select @ins_cmd = 'SQL'
  8246.             if @upd_cmd is NULL  select @upd_cmd = 'SQL'
  8247.             if @del_cmd is NULL  select @del_cmd = 'SQL'
  8248.         end
  8249.  
  8250.         /*
  8251.         ** Parameter Check: @schema_option
  8252.         ** If Autogeneration of custom procedures is not enabled 
  8253.         ** then the default commands will be SQL
  8254.         */
  8255.         IF ((CONVERT(int, @schema_option) & 0x2) = 0)
  8256.         BEGIN
  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.         -- Autogenerate custom procedure names if not provided.
  8263.         -- Use destination table name as the base name by default. 
  8264.     /*    
  8265.         -- Use article name by default. If the name is too long or there's confliction,
  8266.         -- use guid (to prevent proc for diff art in diff pub has same name which cause problems
  8267.         -- when being subscribed by the same subscriber db.
  8268.         if ((@source_object is not NULL and len(@article) > 119) or
  8269.             (@source_object is NULL and len(@article) > 21)) or
  8270.             exists (select * from sysarticles where name = @article)
  8271.         begin
  8272.             set @guid = CONVERT(varbinary(16), LEFT(NEWID(),8))
  8273.             exec @retcode = master.dbo.xp_varbintohexstr @guid, @custom_proc_name OUTPUT
  8274.             if @@error <> 0 or @retcode <> 0
  8275.                 RETURN(1)
  8276.         end
  8277.         else
  8278.             set @custom_proc_name = @article
  8279.     */
  8280.  
  8281.         -- If no command then construct name 
  8282.         if @ins_cmd is NULL
  8283.         begin
  8284.             if (@status & 16) <> 0 -- parameterized
  8285.             begin
  8286.                 if @source_object is not NULL  -- 7.0 format
  8287.                     set @ins_cmd = N'CALL ' + convert (sysname, 'sp_MSins_' + @custom_proc_name)
  8288.                 else -- 6.x compatible
  8289.                     set @ins_cmd = N'CALL ' + convert(nvarchar(30), 'sp_MSins_' + @custom_proc_name)
  8290.             end
  8291.             else
  8292.                 select @ins_cmd = 'SQL'
  8293.         end
  8294.  
  8295.         if @del_cmd is NULL
  8296.         begin
  8297.             if (@status & 16) <> 0 -- parameterized
  8298.             begin
  8299.                 if @source_object is not NULL  -- 7.0 format
  8300.                     set @del_cmd = N'CALL ' + convert (sysname, 'sp_MSdel_' + @custom_proc_name)
  8301.                 else -- 6.x compatible
  8302.                     set @del_cmd = N'CALL ' + convert(nvarchar(30), 'sp_MSdel_' + @custom_proc_name)
  8303.             end
  8304.             else
  8305.                 select @del_cmd = 'SQL'
  8306.         end
  8307.  
  8308.         if @upd_cmd is NULL
  8309.         begin
  8310.             if (@status & 16) <> 0 -- parameterized
  8311.             begin
  8312.                 if @source_object is not NULL  -- 7.0 format
  8313.                     set @upd_cmd = N'MCALL ' + convert (sysname, 'sp_MSupd_' + @custom_proc_name)
  8314.                 else -- 6.x compatible
  8315.                     set @upd_cmd = N'CALL ' + convert(nvarchar(30), 'sp_MSupd_' + @custom_proc_name)
  8316.             end
  8317.             else
  8318.                 select @upd_cmd = 'SQL'
  8319.         end
  8320.  
  8321.         --
  8322.         -- Sync/QueuedTran
  8323.         -- Add guid column if not exists
  8324.         --
  8325.         if (@allow_sync_tran = 1 or @allow_queued_tran = 1)
  8326.         begin
  8327.             SELECT @MSrepl_tran_version_datatype = TYPE_NAME(xtype),
  8328.                 @colid = colid
  8329.             FROM dbo.syscolumns  
  8330.             WHERE id = @tabid AND name = 'msrepl_tran_version'
  8331.  
  8332.             if (@MSrepl_tran_version_datatype IS NULL)
  8333.             begin
  8334.                 --
  8335.                 -- column does not exist, add it
  8336.                 --
  8337.                 if exists (select * from sysobjects where id = @tabid and replinfo & @merge_pub_object_bit <>0)
  8338.                 begin
  8339.                     --if being merged, call stored procedure to add this column.
  8340.                     exec @retcode = sp_repladdcolumn @source_object=@source_table,
  8341.                                                      @column = 'msrepl_tran_version',
  8342.                                                      @typetext= 'uniqueidentifier not null default newid()'
  8343.                     if @@ERROR<>0 or @retcode<>0
  8344.                         return (1)
  8345.                 end
  8346.                 else
  8347.                 begin
  8348.                     exec ('alter table ' + @source_table + ' add msrepl_tran_version uniqueidentifier not null default newid()' )
  8349.                     IF @@ERROR <> 0 
  8350.                         RETURN (1)
  8351.                 end
  8352.             end
  8353.             else
  8354.             begin
  8355.                 --
  8356.                 -- column exists, it should be of type uniqueidentifier
  8357.                 --
  8358.                 if (@MSrepl_tran_version_datatype != 'uniqueidentifier')
  8359.                 begin
  8360.                     raiserror(21192, 16, -1) 
  8361.                     RETURN (1)
  8362.                 end
  8363.  
  8364.                 -- Create the default constraint if it is not there
  8365.                 if not exists (select * from sysconstraints where
  8366.                     id = @tabid and 
  8367.                     colid = @colid and
  8368.                     status & 5 = 5) -- default
  8369.                 begin 
  8370.                     declare @constraint_name sysname
  8371.                     select @constraint_name = 'MSrepl_tran_version_default_' + convert(nvarchar(10), @tabid)
  8372.                     if not exists (select * from sysobjects where name = @constraint_name)
  8373.                     begin
  8374.                         exec ('alter table ' + @source_table + 
  8375.                             ' add constraint ' + @constraint_name + 
  8376.                             ' default newid() for msrepl_tran_version')
  8377.                         if @@ERROR<>0 return 1
  8378.                     end
  8379.                 end
  8380.  
  8381.             end
  8382.         end
  8383.  
  8384.     /*  
  8385.         -- SyncTran
  8386.         -- Add timestamp column if not exists
  8387.         if @allow_sync_tran = 1 and @allow_queued_tran = 0 and ObjectProperty(@tabid, 'TableHasTimestamp') = 0
  8388.         begin
  8389.             exec ('alter table ' + @source_table + ' add msrepl_synctran_ts timestamp not null' )
  8390.             IF @@ERROR <> 0 
  8391.                 RETURN (1)
  8392.         end
  8393.     */
  8394.  
  8395.         -- if concurrent, must use stored procedures at subcriber when replicating commands
  8396.  
  8397.         if @sync_method IN (3,4) and 
  8398.            (lower(@del_cmd) not like N'%call%' or 
  8399.             lower(@ins_cmd) not like N'%call%' or
  8400.             lower(@upd_cmd) not like N'%call%' )
  8401.         begin
  8402.             raiserror( 21153, 16, -1, @article )
  8403.             return 1
  8404.         end
  8405.  
  8406.         -- Identity range support
  8407.             /*
  8408.         ** Parameter Check:  @allow_push.
  8409.         */
  8410.  
  8411.         IF @auto_identity_range IS NULL OR LOWER(@auto_identity_range) NOT IN ('true', 'false')
  8412.             BEGIN
  8413.                 RAISERROR (14148, 16, -1, '@auto_identity_range')
  8414.                 RETURN (1)
  8415.             END
  8416.         IF LOWER(@auto_identity_range) = 'true' 
  8417.         begin
  8418.             if @allow_queued_tran = 0
  8419.             begin
  8420.                 raiserror(21231, 16 ,-1)
  8421.                 return 1
  8422.             end
  8423.             /*
  8424.             ** If you want to have identity support, @range and threshold can not be NULL
  8425.             */
  8426.             if (@pub_identity_range is NULL or @identity_range is NULL or @threshold is NULL)
  8427.                 begin
  8428.                     raiserror(21193, 16, -1)
  8429.                     return (1)
  8430.                 end
  8431.  
  8432.             if OBJECTPROPERTY(@tabid, 'tablehasidentity') <> 1
  8433.             begin
  8434.                 raiserror(21194, 16, -1)
  8435.                 return (1)
  8436.             end
  8437.  
  8438.             if @pub_identity_range <= 1 or @identity_range <= 1
  8439.             begin
  8440.                 raiserror(21232, 16 ,-1)
  8441.                 return 1
  8442.             end
  8443.  
  8444.             if @threshold < 1 or @threshold > 100
  8445.             begin
  8446.                 raiserror(21233, 16 ,-1)
  8447.                 return 1
  8448.             end
  8449.  
  8450.             declare @xtype int, @xprec int, @max_range bigint
  8451.             select @xtype=xtype, @xprec=xprec from syscolumns where id=@tabid and 
  8452.                 columnproperty(id, name, 'IsIdentity')=1
  8453.             select @max_range =
  8454.                     case @xtype when 52 then power((convert(bigint,2)), 8*2-1) - 1 --smallint 
  8455.                         when 48 then power((convert(bigint,2)), 8-1) - 1          --tinyint
  8456.                         when 56 then power((convert(bigint,2)), 8*4-1) - 1          --int
  8457.                         when 127 then power((convert(bigint,2)), 62) - 1 + power((convert(bigint,2)), 62)      --bigint
  8458.                            when 108 then power((convert(bigint,10)), @xprec)      --numeric
  8459.                            when 106 then power((convert(bigint,10)), @xprec)      --decimal
  8460.                      else
  8461.                         power((convert(bigint,2)), 62) + power((convert(bigint,2)), 62) - 1  -- defaulted to bigint
  8462.                     end
  8463.         
  8464.             if @pub_identity_range * 2 + @identity_range > (@max_range - IDENT_CURRENT(@source_table))
  8465.                 begin
  8466.                     raiserror(21290, 16, -1)
  8467.                     return (1)
  8468.                 end
  8469.  
  8470.             -- Set the range to negtive if incr of the identity is negtive
  8471.             if IDENT_INCR(@source_table) < 0
  8472.             begin
  8473.                 select @pub_identity_range = -1 * @pub_identity_range;
  8474.                 select @identity_range = -1 * @identity_range;
  8475.             end
  8476.  
  8477.             -- If the table is already published in queued but is not auto identity
  8478.             -- raiserror error
  8479.             if exists (select * from  sysarticles sa, sysarticleupdates au, syspublications pub where 
  8480.                 sa.objid = @tabid and
  8481.                 au.artid = sa.artid and
  8482.                 au.pubid = pub.pubid and
  8483.                 pub.allow_queued_tran = 1 and 
  8484.                 au.identity_support = 0)
  8485.             begin
  8486.                 raiserror (21240, 16, -1, @source_table)
  8487.                 return (1)
  8488.             end
  8489.  
  8490.             -- If the table is already published in queued and have different auto identity 
  8491.             -- range values, raise error.
  8492.             if exists (select * from MSpub_identity_range where objid=@tabid and 
  8493.             ((pub_range<>@pub_identity_range) or (range <> @identity_range) or (threshold <> @threshold)))
  8494.             begin
  8495.                 raiserror(21291, 16, -1)
  8496.                 return (1)
  8497.             end
  8498.         end
  8499.         else
  8500.         begin
  8501.             -- @auto_identity_range is false
  8502.             -- If the publication is queued and the table has published with auto identity
  8503.             -- already, raise error.
  8504.             if exists (select * from  sysarticles sa, sysarticleupdates au where 
  8505.                 sa.objid = @tabid and
  8506.                 au.artid = sa.artid and
  8507.                 au.identity_support = 1)
  8508.             begin
  8509.                 raiserror (21240, 16, -1, @source_table)
  8510.                 return (1)
  8511.             end
  8512.         end
  8513.  
  8514.         -- SQL insert doesn't work because we need to do 'set identity_insert on/off' 
  8515.         -- before and after the insert.
  8516.         -- The exception is snapshot publication.
  8517.         /* Queue now uses fixed commands. Message 21234 should be removed.
  8518.         if @allow_queued_tran = 1 and OBJECTPROPERTY(@tabid, 'tablehasidentity') = 1 and
  8519.             @ins_cmd = 'SQL' and @repl_freq <> 1
  8520.         begin
  8521.             raiserror(21234, 16, -1)
  8522.             return (1)
  8523.         end
  8524.         */
  8525.  
  8526.         -- Do not allow the table to be published by both merge and queued tran
  8527.         if @allow_queued_tran = 1
  8528.         begin
  8529.             if exists (select * from sysobjects where name = 'sysmergearticles')
  8530.             begin
  8531.                 if exists (select * from sysmergearticles where objid = @tabid)
  8532.                 begin
  8533.                     declare @obj_name sysname
  8534.                     select @obj_name = object_name(@tabid)
  8535.                     raiserror(21266, 16, -1, @obj_name)
  8536.                     return (1)
  8537.                 end
  8538.             end
  8539.         end
  8540.  
  8541.         /*
  8542.         **  Add article to sysarticles and update sysobjects category bit.
  8543.         */
  8544.         -- begin tran
  8545.         begin tran
  8546.         save TRAN sp_addarticle
  8547.  
  8548.         INSERT sysarticles (columns, creation_script, del_cmd, description,
  8549.             dest_table, filter, filter_clause, ins_cmd, name,
  8550.             objid, pre_creation_cmd, pubid,
  8551.             status, sync_objid, type, upd_cmd, schema_option,
  8552.             dest_owner)
  8553.         VALUES (0, @creation_script, @del_cmd, @description, @destination_table,
  8554.             @filterid, @filter_clause, @ins_cmd, @article, @tabid,
  8555.             @precmdid, @pubid, @status, @syncid, @typeid, @upd_cmd, @schema_option, 
  8556.             @destination_owner)
  8557.  
  8558.         IF @@ERROR <> 0
  8559.             goto UNDO
  8560.  
  8561.         SELECT @artid = @@IDENTITY
  8562.  
  8563.         UPDATE sysobjects SET replinfo =  replinfo |  @publish_bit
  8564.             WHERE id = (SELECT objid FROM sysarticles WHERE name = @article 
  8565.                 and pubid =  @pubid)
  8566.  
  8567.         IF @@ERROR <> 0
  8568.             goto UNDO
  8569.  
  8570.         IF @filter IS NOT NULL
  8571.         BEGIN
  8572.             EXEC dbo.sp_MSsetfilterparent @filter, @tabid
  8573.             IF @@ERROR <> 0
  8574.                 goto UNDO
  8575.         END
  8576.  
  8577.         EXEC dbo.sp_MSsetfilteredstatus @tabid
  8578.         IF @@ERROR <> 0
  8579.             goto UNDO
  8580.  
  8581.         /*
  8582.         ** Set all bits to '1' in the columns column to include all columns.
  8583.         */
  8584.  
  8585.         IF @vertical_partition = 'false'
  8586.         BEGIN
  8587.             EXECUTE @retcode  = dbo.sp_articlecolumn @publication, @article
  8588.             -- synctran
  8589.             , @refresh_synctran_procs = 0
  8590.              , @force_invalidate_snapshot = @force_invalidate_snapshot
  8591.       
  8592.             IF @@ERROR <> 0 OR @retcode <> 0
  8593.                 goto UNDO
  8594.         END
  8595.     
  8596.         /*
  8597.         ** 1. Set all bits to '1' for all columns in the primary key.
  8598.         ** 2. Set version column bit to 1 if the publication is synctran
  8599.         ** 3. For queued replication, set all column bits to 1 that do not allow
  8600.         **        NULL or DEFAULT value
  8601.         */
  8602.         ELSE
  8603.         BEGIN
  8604.             --
  8605.             -- for updating subscribers build a temp table
  8606.             -- to keep track of columns that are mandatory
  8607.             --
  8608.             if (@allow_sync_tran = 1 or @allow_queued_tran = 1)
  8609.             begin
  8610.                 create table #pktable(name sysname collate database_default)
  8611.             end
  8612.             
  8613.             --
  8614.             -- if it's a table, get the indid of the PK
  8615.             --
  8616.             if exists( select * from sysobjects where id = @tabid and xtype = 'U' )
  8617.             begin
  8618.                 SELECT @indid = indid FROM sysindexes
  8619.                 WHERE id = @tabid
  8620.                 AND (status & 2048) <> 0    /* PK index */
  8621.             end
  8622.             else  -- else it's a mview, use the CI (which, for a MV, must be unique)        
  8623.             begin
  8624.                 SELECT @indid = 1
  8625.             end
  8626.  
  8627.             /*
  8628.             **  First we'll figure out what the keys are.
  8629.             */
  8630.             SELECT @i = 1
  8631.  
  8632.             WHILE (@i <= 16)
  8633.             BEGIN
  8634.                 SELECT @pkkey = INDEX_COL(@source_table, @indid, @i)
  8635.                 if @pkkey is NULL
  8636.                     break
  8637.  
  8638.                 EXECUTE @retcode  = dbo.sp_articlecolumn @publication,
  8639.                     @article, @pkkey, 'add'
  8640.                     -- synctran
  8641.                     , @refresh_synctran_procs = 0
  8642.                     , @force_invalidate_snapshot = @force_invalidate_snapshot
  8643.                 IF @@ERROR <> 0 OR @retcode <> 0
  8644.                     goto UNDO
  8645.  
  8646.                 if (@allow_sync_tran = 1 or @allow_queued_tran = 1)
  8647.                     insert into #pktable(name) values(@pkkey)
  8648.                     
  8649.                 select @i = @i + 1
  8650.             END
  8651.  
  8652.             if (@allow_sync_tran = 1 or @allow_queued_tran = 1)
  8653.             BEGIN
  8654.                 --
  8655.                 -- The version column needs to go in
  8656.                 --
  8657.                 declare @version_col sysname
  8658.                 -- Get synctran column
  8659.                 select @version_col = 'msrepl_tran_version'
  8660.                 EXECUTE @retcode  = dbo.sp_articlecolumn @publication,
  8661.                     @article, @version_col, 'add'
  8662.                     -- synctran
  8663.                     , @refresh_synctran_procs = 0
  8664.                     , @force_invalidate_snapshot = @force_invalidate_snapshot
  8665.  
  8666.                 IF @@ERROR <> 0 OR @retcode <> 0
  8667.                     goto UNDO
  8668.  
  8669.                 insert into #pktable(name) values('msrepl_tran_version')
  8670.  
  8671.                 --
  8672.                 -- select the columns that are not IDENTITY columns
  8673.                 -- and do not allow NULL 
  8674.                 -- and do not have any DEFAULT constraints defined for them
  8675.                 -- and have not been processed already
  8676.                 -- (IDENTITY columns do not need to be referenced explicitly - 
  8677.                 -- which is like having a DEFAULT value so they can be excluded)
  8678.                 --
  8679.                 declare #htemp cursor local fast_forward for
  8680.                     select name from dbo.syscolumns 
  8681.                     where id = @tabid and isnullable = 0 
  8682.                         and cdefault = 0 
  8683.                         and ColumnProperty(id, name, N'IsIdentity') != 1
  8684.                         and name not in (select name from #pktable)    
  8685.  
  8686.                 open #htemp
  8687.                 fetch #htemp into @version_col
  8688.                 while (@@fetch_status = 0)
  8689.                 begin
  8690.                     EXECUTE @retcode  = dbo.sp_articlecolumn @publication,
  8691.                     @article, @version_col, 'add', @refresh_synctran_procs = 0
  8692.                     , @force_invalidate_snapshot = @force_invalidate_snapshot
  8693.  
  8694.                     IF (@@ERROR != 0 OR @retcode != 0)
  8695.                     BEGIN
  8696.                         close #htemp
  8697.                         deallocate #htemp
  8698.                         drop table #pktable
  8699.                         goto UNDO
  8700.                     END
  8701.                     fetch #htemp into @version_col
  8702.                 end
  8703.                 close #htemp
  8704.                 deallocate #htemp
  8705.                 drop table #pktable
  8706.             END
  8707.         end -- IF @vertical_partition = 'false' ELSE
  8708.  
  8709.         ------------------------------------------------------------------------------
  8710.         -- if table based article does not use a view for sync, create one and use it
  8711.         ------------------------------------------------------------------------------
  8712.  
  8713.         if @tabid = @syncid 
  8714.         begin
  8715.             -- generate view name
  8716.  
  8717.             declare @viewname varchar(255)
  8718.  
  8719.             set @guid = CONVERT(varbinary(16), LEFT(NEWID(),8))
  8720.             exec @retcode = master.dbo.xp_varbintohexstr @guid, @viewname OUTPUT
  8721.             if @@ERROR <> 0 OR @retcode <> 0
  8722.                 goto UNDO
  8723.             
  8724.             set @viewname = 'syncobj_' + @viewname
  8725.  
  8726.             -- create view for object synchronization
  8727.             if ((@allow_sync_tran = 1 or @allow_queued_tran = 1) 
  8728.                 and @vertical_partition = 'true')
  8729.             begin
  8730.                 --
  8731.                 -- vertical partition is true - this means we may not have the 
  8732.                 -- complete view yet - column could be added or dropped.
  8733.                 -- we do not want to validate the provided filter clause now
  8734.                 -- sp_articlefilter will be called explicitly later to add article 
  8735.                 -- filter and sp_articleview will be called finally to regenerate the 
  8736.                 -- view - and the filter validation will be done then for updating subscribers
  8737.                 --
  8738.                 exec @retcode = dbo.sp_articleview @publication, @article, @viewname, NULL
  8739.                     ,@force_invalidate_snapshot = @force_invalidate_snapshot
  8740.             end
  8741.             else
  8742.             begin
  8743.                 exec @retcode = dbo.sp_articleview @publication, @article, @viewname, @filter_clause
  8744.                     ,@force_invalidate_snapshot = @force_invalidate_snapshot
  8745.             end
  8746.             if @@ERROR <> 0 OR @retcode <> 0
  8747.                 goto UNDO
  8748.         end
  8749.  
  8750.         -- Need to change syscolumns status before generating sync procs because the
  8751.         -- status will be used to decide whether or not call set identity insert.
  8752.         IF LOWER(@auto_identity_range) = 'true' 
  8753.         begin
  8754.             -- Make the identity column as not for replication
  8755.             select @colid = null
  8756.             select @colid = colid from syscolumns  where
  8757.                  id = @tabid and
  8758.                  colstat & 0x0001 <> 0 and -- is identity
  8759.                  colstat & 0x0008 = 0 -- No 'not for repl' property
  8760.             if @colid is not null
  8761.             begin
  8762.                 exec @retcode  = dbo.sp_replupdateschema @source_table
  8763.                 -- Mark 'not for repl'
  8764.                 update syscolumns set colstat = colstat | 0x0008 where
  8765.                     id = @tabid and colid = @colid
  8766.                 -- Single to refresh the object cache.
  8767.                 exec @retcode  = dbo.sp_replupdateschema @source_table
  8768.                 IF @@ERROR <> 0 OR @retcode <> 0
  8769.                     goto UNDO
  8770.             end
  8771.         end
  8772.  
  8773.         /* 
  8774.         ** if @autogen_sync_procs_id is 1, autogen the sync tran procs, including name 
  8775.         */
  8776.         if @tabid > 0 and @autogen_sync_procs_id = 1
  8777.         begin
  8778.             declare @insproc sysname, @updproc sysname, @delproc sysname, @updtrig sysname
  8779.             select @insproc   = 'sp_MSsync_ins_'+ SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @pubid))
  8780.             select @updproc   = 'sp_MSsync_upd_'+ SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @pubid))
  8781.             select @delproc   = 'sp_MSsync_del_'+ SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @pubid))
  8782.             select @updtrig   = 'sp_MSsync_upd_trig_'+ SUBSTRING(RTRIM(@article), 1, 100) + '_' + rtrim(convert(varchar, @pubid))
  8783.  
  8784.             -- check uniqueness of names and revert to ugly guid-based name if friendly name already exists
  8785.             if exists (select name from sysobjects where name in (@insproc, @updproc, @delproc, @updtrig))
  8786.             begin
  8787.                 declare @guid_name nvarchar(36)
  8788.                 select @guid_name =  convert (nvarchar(36), newid())
  8789.                 -- remove '-' from guid name because rpc can't handle '-'
  8790.                 select @guid_name = replace (@guid_name,'-','_')
  8791.                 select @insproc = 'sp_MSsync_ins_' + @guid_name
  8792.                 select @updproc = 'sp_MSsync_upd_' + @guid_name
  8793.                 select @delproc = 'sp_MSsync_del_' + @guid_name
  8794.                 select @updtrig = 'sp_MSsync_upd_trig_' + @guid_name
  8795.             end
  8796.  
  8797.             if @insproc IS NULL
  8798.             begin
  8799.                 RAISERROR (14043, 11, -1, '@insproc')
  8800.                 goto UNDO
  8801.             end
  8802.  
  8803.             if @updproc IS NULL
  8804.             begin
  8805.                 RAISERROR (14043, 11, -1, '@updproc')
  8806.                 goto UNDO
  8807.             end
  8808.  
  8809.             if @delproc IS NULL
  8810.             begin
  8811.                 RAISERROR (14043, 11, -1, '@delproc')
  8812.                 goto UNDO
  8813.             end
  8814.  
  8815.  
  8816.             if @updtrig IS NULL
  8817.             begin
  8818.                 RAISERROR (14043, 11, -1, '@updtrig')
  8819.                 goto UNDO
  8820.             end
  8821.  
  8822.  
  8823.             exec @retcode = dbo.sp_articlesynctranprocs @publication, @article, @insproc, @updproc, @delproc, true, @updtrig
  8824.  
  8825.             IF @@ERROR <> 0 OR @retcode <> 0
  8826.                 goto UNDO
  8827.         end
  8828.         -- end SyncTran
  8829.  
  8830.         -- Generate the conflict table and conflict proc for Queued Tran case
  8831.         if (@allow_queued_tran = 1)
  8832.         begin
  8833.             exec @retcode = dbo.sp_MSmakeconflicttable @article, @publication, 0
  8834.             IF @@ERROR <> 0 OR @retcode <> 0
  8835.                 goto UNDO
  8836.             exec @retcode = dbo.sp_MSmaketrancftproc @article, @publication
  8837.             IF @@ERROR <> 0 OR @retcode <> 0
  8838.                 goto UNDO
  8839.         end 
  8840.  
  8841.         IF LOWER(@auto_identity_range) = 'true' 
  8842.         begin
  8843.             -- Have to do the update below after sync proc generation since
  8844.             -- it will insert row to sysarticleupdates
  8845.             update sysarticleupdates set identity_support = 1 where artid = @artid
  8846.             IF @@ERROR <> 0
  8847.                 goto UNDO
  8848.             
  8849.             -- It is possible that the table is already being published. If so
  8850.             -- keep the old identity range values.
  8851.             if not exists (select * from MSpub_identity_range where objid = @tabid)
  8852.             begin
  8853.                 insert into MSpub_identity_range (objid, range, pub_range, current_pub_range, last_seed, threshold) 
  8854.                     values (@tabid, @identity_range, @pub_identity_range, @pub_identity_range, null, @threshold) 
  8855.                 IF @@ERROR <> 0
  8856.                     goto UNDO
  8857.             
  8858.                 -- Call stored procedure to reconcile identity range
  8859.                 exec @retcode = dbo.sp_MSpub_adjust_identity @artid = @artid
  8860.                 IF @@ERROR <> 0 OR @retcode <> 0
  8861.                     goto UNDO
  8862.             end                    
  8863.         end -- IF LOWER(@auto_identity_range) = 'true' 
  8864.     END -- End of the else block handle table articles.
  8865.  
  8866.     -- 0x00001000 collation
  8867.     -- 0x00002000 extended property
  8868.     -- @schema_option is already padded out at the beginning of this procedure
  8869.  
  8870.     SELECT @schema_option_int = fn_replgetbinary8lodword(@schema_option)
  8871.     IF ((@schema_option_int & 0x00001000 <>0 ) or 
  8872.         (@schema_option_int & 0x00002000 <> 0 ))
  8873.         select @backward_comp_level = 40
  8874.     if @backward_comp_level > 10
  8875.         update syspublications set backward_comp_level = @backward_comp_level where pubid = @pubid
  8876.  
  8877.     /*
  8878.     ** Get distribution server information for remote RPC call.
  8879.     */
  8880.     EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  8881.        @distribdb   = @distribdb OUTPUT
  8882.     IF @@ERROR <> 0 or @retcode <> 0
  8883.         goto UNDO
  8884.  
  8885.     SELECT @dbname =  DB_NAME()
  8886.     
  8887.     SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  8888.         '.dbo.sp_MSadd_article'
  8889.     EXECUTE @retcode = @distproc
  8890.         @publisher = @@SERVERNAME,
  8891.         @publisher_db = @dbname,
  8892.         @publication = @publication,
  8893.         @article = @article,
  8894.         @article_id = @artid,
  8895.         @destination_object = @destination_table,
  8896.         @source_owner = @source_owner,
  8897.         @source_object = @bak_source,
  8898.         @description = @description
  8899.  
  8900.     IF @@ERROR <> 0 OR @retcode <> 0
  8901.         goto UNDO
  8902.     
  8903.     /* If the publication is immediate_sync type
  8904.     ** 1. Change the immediate_sync_ready status to false 
  8905.     ** 2. Add a virtual subscription on the article 
  8906.     ** 3. Add subscriptions for all the subscriber
  8907.     ** that have no_sync subscriptions on the publication
  8908.     **
  8909.     ** Note: Subscriptions for subscribers that have automatic sync subscriptions
  8910.     ** on the publication will be added by snasphot agent.
  8911.     */
  8912.     if EXISTS (SELECT *    FROM syspublications WHERE
  8913.         name = @publication    AND
  8914.         immediate_sync = 1 )
  8915.     BEGIN
  8916.         EXECUTE @retcode  = dbo.sp_addsubscription 
  8917.             @publication = @publication, 
  8918.             @article = @article, 
  8919.             @subscriber = NULL, 
  8920.             @destination_db = 'virtual', 
  8921.             @sync_type = 'automatic', 
  8922.             @status = NULL, 
  8923.             @reserved = 'internal'
  8924.         IF @@ERROR <> 0 OR @retcode <> 0
  8925.             GOTO UNDO
  8926.  
  8927.         -- Note: We have to add the subscriptions to the new article before 
  8928.         -- the virtual subscriptions being activated!!!! Otherwise, the snapshot 
  8929.         -- transactions may be skipped by dist agents.
  8930.         EXECUTE @retcode  = dbo.sp_refreshsubscriptions @publication
  8931.  
  8932.         IF @@ERROR <> 0 OR @retcode <> 0
  8933.             GOTO UNDO
  8934.         
  8935.         -- Have to call this stored procedure to invalidate existing snapshot
  8936.         -- if there are any. 
  8937.         EXECUTE @retcode  = dbo.sp_MSreinit_article
  8938.             @publication = @publication, 
  8939.             -- Virtual subscriptions of all the articles will be deactivated.
  8940.             -- @article = @article,
  8941.             @need_new_snapshot = 1,
  8942.             @force_invalidate_snapshot = @force_invalidate_snapshot    
  8943.         IF @@ERROR <> 0 OR @retcode <> 0
  8944.             GOTO UNDO
  8945.     END
  8946.  
  8947.     COMMIT TRANSACTION
  8948.     return 0
  8949. UNDO:
  8950.     if @@trancount > 0
  8951.     begin
  8952.         ROLLBACK TRANSACTION sp_addarticle
  8953.         commit tran
  8954.     end
  8955.     RETURN (1)
  8956. go
  8957.  
  8958. /*
  8959. ** Create replication stored procedures.
  8960. ** Part 1:  create codependent procedures.
  8961. */
  8962.  
  8963. EXEC dbo.sp_MS_marksystemobject sp_addarticle
  8964. GO
  8965.  
  8966. print ''
  8967. print 'Creating procedure sp_MSgettranconflictname'
  8968. go
  8969. CREATE PROCEDURE sp_MSgettranconflictname (
  8970. @publication sysname,
  8971. @source_object nvarchar(540),
  8972. @str_prefix nvarchar(30) = NULL,
  8973. @conflict_table sysname = NULL OUTPUT)
  8974. AS
  8975. begin
  8976.     declare @objid                 int
  8977.     declare @retcode            int
  8978.     declare @object_name        sysname
  8979.     declare @name_out            sysname
  8980.     declare @pubid                int
  8981.     declare @article            sysname
  8982.     declare @artid                int
  8983.     declare @prefixlen            int
  8984.  
  8985.     if (@str_prefix is NULL)
  8986.         select @str_prefix = 'conflict_'
  8987.  
  8988.     select @prefixlen = len(@str_prefix)
  8989.  
  8990.     select @pubid=pubid from syspublications 
  8991.         where name=@publication
  8992.  
  8993.     select @objid = object_id(@source_object)
  8994.     select @artid = artid, @article=name from sysarticles 
  8995.         where objid = @objid and pubid=@pubid
  8996.  
  8997.     if len(@publication) + len(@article) > 128 - @prefixlen -1     -- SYSNAME minus prefix len
  8998.     begin
  8999.         select @object_name = @str_prefix + 
  9000.             convert(nvarchar(59), @publication) + 
  9001.             '_' + convert(nvarchar(59), @article)
  9002.     end
  9003.     else
  9004.     begin
  9005.         select @object_name = @str_prefix + @publication + '_' + @article
  9006.     end
  9007.     select @conflict_table = @object_name
  9008.     exec @retcode = dbo.sp_MSuniqueobjectname @object_name, @conflict_table OUTPUT
  9009. end
  9010. GO
  9011. EXEC dbo.sp_MS_marksystemobject sp_MSgettranconflictname
  9012. GO
  9013.  
  9014. print ''
  9015. print 'Creating procedure sp_MSmaketrancftproc'
  9016. go
  9017.  
  9018. create procedure sp_MSmaketrancftproc (
  9019.     @article sysname, 
  9020.     @publication sysname,
  9021.     @is_debug bit=0)
  9022. as
  9023. BEGIN
  9024. declare @source_table nvarchar(540)
  9025.         ,@owner sysname
  9026.         ,@procname sysname
  9027.         ,@source_objid int
  9028.         ,@artid int
  9029.         ,@pubid int
  9030.         ,@conflict_tableid int
  9031.         ,@conflict_table    sysname
  9032.         ,@conflict_proc_id int
  9033.         ,@indid int
  9034.         ,@indkey int
  9035.         ,@ind_col_name sysname
  9036.         ,@qualname   nvarchar(266)
  9037.         ,@dbname sysname
  9038.         ,@retcode smallint
  9039.         ,@retain_varname int
  9040.  
  9041. declare @colid        int
  9042.         ,@colname    sysname
  9043.         ,@coltype    sysname
  9044.         ,@ccoltype    sysname
  9045.         ,@rowcnt    int
  9046.  
  9047. declare @argtabempty    bit
  9048.         ,@seltabempty    bit
  9049.         ,@sel2tabempty    bit
  9050.         ,@valtabempty     bit
  9051.         ,@paramtabempty    bit
  9052.         ,@where_clausetabempty bit
  9053.         ,@decltabempty bit
  9054.         ,@assigntabempty bit
  9055.         ,@compinsertabempty bit
  9056.  
  9057. declare @argterm    nvarchar(4000)
  9058.         ,@selterm    nvarchar(4000)
  9059.         ,@sel2term    nvarchar(4000)
  9060.         ,@updterm    nvarchar(4000)
  9061.         ,@valterm     nvarchar(4000)
  9062.         ,@paramterm    nvarchar(4000)
  9063.         ,@where_term nvarchar(4000)
  9064.         ,@declterm    nvarchar(4000)
  9065.         ,@assignterm nvarchar(4000)
  9066.         ,@compinsterm nvarchar(4000)
  9067.  
  9068. declare @cmd        nvarchar(4000)
  9069.  
  9070. set nocount on
  9071.  
  9072. --
  9073. -- prepare the proc name and get the other parameters
  9074. --
  9075. select @artid = a.artid, @pubid = a.pubid, @source_table = object_name(a.objid), 
  9076.         @source_objid = a.objid 
  9077. from sysarticles a, syspublications p
  9078.         where a.name = @article and
  9079.               p.name = @publication and
  9080.               a.pubid = p.pubid
  9081.  
  9082. -- Get the object owner name
  9083. select @owner = u.name 
  9084. from sysusers u, sysobjects o 
  9085. where o.id = @source_objid and o.uid = u.uid
  9086.  
  9087. --
  9088. -- Prepare the proc name 
  9089. -- The source table should be owner qualified
  9090. --
  9091. select @source_table = QUOTENAME(@owner) + N'.' + QUOTENAME(@source_table)
  9092. exec @retcode = sp_MSgettranconflictname @publication=@publication, 
  9093.                     @source_object= @source_table, 
  9094.                     @str_prefix='sp_MScft_', 
  9095.                     @conflict_table=@procname OUTPUT
  9096.  
  9097. --
  9098. -- The conflict table should exist before we do any conflict procs
  9099. --
  9100. select @conflict_tableid = conflict_tableid, 
  9101.         @conflict_table = OBJECT_NAME(conflict_tableid) 
  9102. from sysarticleupdates
  9103. where artid = @artid and pubid = @pubid
  9104. if ( @conflict_tableid is NULL)
  9105.     return (1)
  9106. --
  9107. -- To check if specified object exists in current database
  9108. --
  9109. if (@owner is null or @owner = ' ')
  9110.     set @qualname = QUOTENAME(@conflict_table)
  9111. else
  9112.     set @qualname = QUOTENAME(@owner) + '.' + QUOTENAME(@conflict_table)
  9113.  
  9114. if (object_id(@qualname) is NULL)
  9115.     return (1)
  9116.  
  9117. --
  9118. -- The source table should have an unique index
  9119. --
  9120. exec @indid = dbo.sp_MStable_has_unique_index @source_objid
  9121. if (@indid = 0)
  9122.     return (1)
  9123.  
  9124. --
  9125. -- Get all the columns participating in the index of the source table
  9126. --
  9127. create table #indcoltab ( colname sysname collate database_default )
  9128. select @indkey = 1;
  9129. while (@indkey <= 16)
  9130. begin
  9131.     select @ind_col_name = index_col(@source_table, @indid, @indkey)
  9132.     if (@ind_col_name is not NULL) 
  9133.         insert into #indcoltab(colname) values(@ind_col_name)
  9134.     else
  9135.         select @indkey = 16
  9136.  
  9137.     select @indkey = @indkey + 1
  9138. end
  9139.  
  9140. -- build the lists
  9141. select @argtabempty = 1
  9142.     ,@valtabempty = 1
  9143.     ,@paramtabempty = 1
  9144.     ,@seltabempty = 1
  9145.     ,@sel2tabempty = 1
  9146.     ,@decltabempty = 1
  9147.     ,@assigntabempty = 1
  9148.     ,@where_clausetabempty = 1
  9149.     ,@compinsertabempty = 1
  9150.  
  9151. create table #argtab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9152. create table #valtab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9153. create table #paramtab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9154. create table #seltab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9155. create table #sel2tab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9156. create table #decltab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9157. create table #assigntab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9158. create table #where_clausetab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9159. create table #compinstab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  9160.  
  9161. -- some predefined declares and assignments
  9162. select @cmd = N'
  9163.     declare @reinit_code int, @subwins_code int, @pubwins_code int, @qcfttabrowid uniqueidentifier
  9164.             ,@retcode smallint, @compcmd nvarchar(4000), @centralized_conflicts bit'
  9165. insert into #decltab(procedure_text) values(@cmd)
  9166. select @decltabempty = 0
  9167.     
  9168. select @cmd = N'
  9169.     select @reinit_code = 3
  9170.             ,@subwins_code = 2
  9171.             ,@pubwins_code = 1
  9172.             ,@qcfttabrowid = NEWID()'
  9173. insert into #assigntab(procedure_text) values(@cmd)
  9174. select @cmd = N'
  9175.     select @centralized_conflicts = centralized_conflicts
  9176.     from dbo.syspublications where pubid = ' + cast(@pubid as nvarchar)
  9177. insert into #assigntab(procedure_text) values(@cmd)
  9178. select @assigntabempty = 0
  9179.     
  9180. declare #argcursor cursor local FAST_FORWARD FOR 
  9181.         select colid
  9182.         from syscolumns
  9183.         where iscomputed = 0 and id=@conflict_tableid 
  9184.         order by colid
  9185. FOR READ ONLY
  9186.  
  9187. select @retain_varname = 0
  9188. open #argcursor
  9189. fetch #argcursor into @colid
  9190. while (@@FETCH_STATUS = 0)
  9191. begin
  9192.     --
  9193.     -- Get the column name and column type
  9194.     --
  9195.     exec dbo.sp_MSget_type @conflict_tableid, @colid, @colname output, @coltype OUTPUT
  9196.     if (@@ERROR<>0 or @retcode<>0)
  9197.         return (1)
  9198.  
  9199.     --
  9200.     -- skip this specific column or if type is not returned
  9201.     --
  9202.     if ((@coltype IS NULL) or (LOWER(@colname) = 'qcfttabrowid'))
  9203.     begin
  9204.         -- do the next fetch and continue
  9205.         fetch #argcursor into @colid
  9206.         continue    
  9207.     end
  9208.         
  9209.     exec dbo.sp_MSget_colinfo @conflict_tableid, @colid, NULL, 0, NULL, @ccoltype output
  9210.     if (@@ERROR<>0 or @retcode<>0)
  9211.         return (1)
  9212.  
  9213.     --
  9214.     -- parameterize the vars that are the column values of the source
  9215.     -- table. For the columns that are specific to the conflict table
  9216.     -- retain specific names for the vars
  9217.     --
  9218.     if (LOWER(@colname) = 'origin_datasource')
  9219.         select @retain_varname = @colid
  9220.  
  9221.     if (@retain_varname = 0)
  9222.         select @argterm = N'@param' + cast(@colid as nvarchar) 
  9223.     else
  9224.         select @argterm = N'@' + @colname
  9225.         
  9226.     select @valterm = quotename(@colname)
  9227.     select @paramterm = @argterm
  9228.     select @updterm = @valterm + N' = ' + @argterm
  9229.  
  9230.     if (@retain_varname = 0)
  9231.     begin
  9232.         select @selterm = @paramterm + N' = ' + @valterm
  9233.         select @sel2term = @paramterm + N' = case when ' + @paramterm + 
  9234.                     N' is NULL then ' + @valterm + N' else ' + @paramterm + N' end'
  9235.     end
  9236.     else
  9237.     begin
  9238.         select @selterm = NULL
  9239.         select @sel2term = NULL
  9240.     end
  9241.      
  9242.     select @argterm = @argterm + N' ' + @coltype
  9243.  
  9244.     -- Check if this is part of primary key    / unique index
  9245.     if (@colname in ( select colname from #indcoltab ) )
  9246.     begin
  9247.         -- this key assignment becomes part of where clause
  9248.         select @where_term = @updterm
  9249.         select @updterm = NULL
  9250.         select @selterm = NULL
  9251.         select @sel2term = NULL
  9252.     end
  9253.     else
  9254.         select @where_term = NULL
  9255.  
  9256.     -- special columns - process them as local var
  9257.     if (LOWER(@colname) = 'insertdate' )
  9258.     begin
  9259.         select @declterm = N'
  9260.     declare ' + @argterm
  9261.         select @assignterm = N'
  9262.     select ' + @paramterm + N' = GETDATE()'
  9263.         select @argterm = NULL
  9264.     end
  9265.     else if (LOWER(@colname) = 'pubid' )
  9266.     begin
  9267.         select @declterm = N'
  9268.     declare ' + @argterm
  9269.         select @assignterm = N'
  9270.     select ' + @paramterm + N' = ' + cast(@pubid as nvarchar)
  9271.         select @argterm = NULL
  9272.     end
  9273.     else
  9274.     begin
  9275.         select @declterm = NULL
  9276.         select @assignterm = NULL
  9277.     end
  9278.  
  9279.     -- build the term for compensating insert
  9280.     if (lower(@ccoltype) = 'varchar')
  9281.         select @compinsterm = N' '''''' + master.dbo.fn_MSgensqescstr(' + @valterm + N') collate database_default + '''''''' '
  9282.     else if (lower(@ccoltype) = 'nvarchar')
  9283.         select @compinsterm = N' N'''''' + master.dbo.fn_MSgensqescstr(' + @valterm + N') collate database_default + '''''''' '
  9284.     else if (lower(@ccoltype) = 'char')
  9285.         select @compinsterm = N' '''''' + master.dbo.fn_MSgensqescstr(CAST(RTRIM(' + @valterm + N') as nvarchar(4000))) collate database_default + '''''''' '
  9286.     else if (lower(@ccoltype) = 'nchar')
  9287.         select @compinsterm = N' N'''''' + master.dbo.fn_MSgensqescstr(CAST(RTRIM(' + @valterm + N') as nvarchar(4000))) collate database_default + '''''''' '
  9288.     else if (lower(@ccoltype) in ('binary','varbinary'))
  9289.         select @compinsterm = N' '' + master.dbo.fn_varbintohexstr(' + @valterm + N') collate database_default ' 
  9290.     else if (lower(@ccoltype) in ('bit','bigint','int','smallint','tinyint','float','real','decimal','numeric'))
  9291.         select @compinsterm = N' '' + CAST(' + @valterm + N' as nvarchar) '
  9292.     else if (lower(@ccoltype) in ('money','smallmoney'))
  9293.         select @compinsterm = N' '' + CONVERT(nvarchar(40),' + @valterm + N', 2) '
  9294.     else if (lower(@ccoltype) = 'uniqueidentifier')
  9295.         select @compinsterm = N' '''''' + CAST(' + @valterm + N' as nvarchar(40)) + '''''''' '
  9296.     else if (lower(@ccoltype) in ('datetime','smalldatetime'))
  9297.         select @compinsterm = N' '''''' + CONVERT(nvarchar(40), ' + @valterm + N', 121) + '''''''' '
  9298.     else if (lower(@ccoltype) = 'sql_variant')
  9299.         select @compinsterm = N' '' + master.dbo.fn_sqlvarbasetostr(' + @valterm + N' ) collate database_default '
  9300.     else
  9301.         select @compinsterm = N' '' + CAST(' + @valterm + N' as nvarchar) '
  9302.     
  9303.     -- Now append to the various lists
  9304.     if (@argterm is NOT NULL)
  9305.     begin        
  9306.         if (@argtabempty = 1)
  9307.         begin
  9308.             select @argtabempty = 0
  9309.             select @cmd = N'
  9310.     ' + @argterm
  9311.         end
  9312.         else
  9313.             select @cmd = N',
  9314.     ' + @argterm
  9315.         insert into #argtab(procedure_text) values(@cmd)
  9316.     end
  9317.     if (@valterm is NOT NULL)
  9318.     begin
  9319.         if (@valtabempty = 1)
  9320.         begin
  9321.             select @valtabempty = 0
  9322.             select @cmd = @valterm
  9323.         end
  9324.         else
  9325.             select @cmd = N', ' + @valterm
  9326.         insert into #valtab(procedure_text) values(@cmd)
  9327.     end
  9328.     if (@paramterm is NOT NULL)
  9329.     begin
  9330.         if (@paramtabempty = 1)
  9331.         begin
  9332.             select @paramtabempty = 0
  9333.             select @cmd = @paramterm
  9334.         end
  9335.         else
  9336.             select @cmd = N', ' + @paramterm
  9337.         insert into #paramtab(procedure_text) values(@cmd)
  9338.     end
  9339.     if (@selterm is NOT NULL)
  9340.     begin
  9341.         if (@seltabempty = 1)
  9342.         begin
  9343.             select @seltabempty = 0
  9344.             select @cmd = N'
  9345.         ' + @selterm
  9346.         end
  9347.         else
  9348.             select @cmd = N'
  9349.         ,' + @selterm        
  9350.         insert into #seltab(procedure_text) values(@cmd)
  9351.     end
  9352.     if (@sel2term is NOT NULL)
  9353.     begin
  9354.         if (@sel2tabempty = 1)
  9355.         begin
  9356.             select @sel2tabempty = 0
  9357.             select @cmd = N'
  9358.         ' + @sel2term
  9359.         end
  9360.         else
  9361.             select @cmd = N'
  9362.         ,' + @sel2term        
  9363.         insert into #sel2tab(procedure_text) values(@cmd)
  9364.     end    
  9365.     if (@where_term is NOT NULL)
  9366.     begin
  9367.         if (@where_clausetabempty = 1)
  9368.         begin
  9369.             select @where_clausetabempty = 0
  9370.             select @cmd = @where_term
  9371.         end
  9372.         else
  9373.             select @cmd = N' AND 
  9374.             ' + @where_term
  9375.         insert into #where_clausetab(procedure_text) values(@cmd)
  9376.     end
  9377.     if (@declterm is NOT NULL)
  9378.     begin
  9379.         select @cmd = @declterm + N'
  9380.     '
  9381.         insert into #decltab(procedure_text) values(@cmd)
  9382.     end        
  9383.  
  9384.     if (@assignterm is NOT NULL)
  9385.     begin
  9386.         select @cmd = @assignterm + N'
  9387.     '
  9388.         insert into #assigntab(procedure_text) values(@cmd)
  9389.     end        
  9390.  
  9391.     if (@compinsterm is NOT NULL)
  9392.     begin
  9393.         if (@compinsertabempty = 1)
  9394.         begin
  9395.             select @compinsertabempty = 0
  9396.             select @cmd = N' + ISNULL(''' + @compinsterm + N', ''null'')'
  9397.         end
  9398.         else
  9399.             select @cmd = N' + ISNULL('',' + @compinsterm + N', ''null'')'
  9400.         insert into #compinstab(procedure_text) values(@cmd)
  9401.     end
  9402.     
  9403.     -- do the next fetch
  9404.     fetch #argcursor into @colid
  9405.  
  9406. end
  9407. close #argcursor
  9408. deallocate #argcursor
  9409. drop table #indcoltab
  9410.  
  9411. --
  9412. -- generation phase
  9413. --
  9414. BEGIN TRAN sp_MSmaketrancftproc
  9415.  
  9416. -- create temp table to select the command text out of
  9417. if exists (select * from sysobjects where name = 'tempcmd' and uid = user_id('dbo'))
  9418.         drop table dbo.tempcmd
  9419. create table dbo.tempcmd ( c1 int identity NOT NULL, cmdtext nvarchar(4000) NULL)
  9420.  
  9421. -- create header
  9422. insert into  dbo.tempcmd(cmdtext) 
  9423. values(N'create procedure '+QUOTENAME(@owner)+ N'.'+ QUOTENAME(@procname) + N'( 
  9424. ')
  9425.  
  9426. -- insert the arglist
  9427. insert into dbo.tempcmd(cmdtext) select procedure_text from #argtab order by c1 
  9428. insert into dbo.tempcmd(cmdtext) values(N' ,@subcriber sysname = NULL, @subdb sysname = NULL )
  9429. as
  9430. begin
  9431. ')
  9432.  
  9433. -- insert the declare list
  9434. insert into dbo.tempcmd(cmdtext) select procedure_text from #decltab order by c1 
  9435. insert into dbo.tempcmd(cmdtext) values(N'
  9436. ')
  9437.  
  9438. -- insert the assignment list (for declared vars)
  9439. insert into dbo.tempcmd(cmdtext) select procedure_text from #assigntab order by c1
  9440.  
  9441. -- do the select for the case where we need to retain values of publisher
  9442. insert into dbo.tempcmd(cmdtext) values(N'
  9443.     if (@reason_code = @subwins_code)
  9444.     begin
  9445.         select ')
  9446. insert into dbo.tempcmd(cmdtext) select procedure_text from #seltab order by c1
  9447. insert into dbo.tempcmd(cmdtext) values(N'
  9448.         from ' + @source_table + N' where ')
  9449. insert into dbo.tempcmd(cmdtext) select procedure_text from #where_clausetab order by c1
  9450. insert into dbo.tempcmd(cmdtext) values(N'
  9451.     end')
  9452.  
  9453. insert into dbo.tempcmd(cmdtext) values(N'
  9454.     else
  9455.     begin
  9456.         select ')
  9457.     
  9458. insert into dbo.tempcmd(cmdtext) select procedure_text from #sel2tab order by c1
  9459. insert into dbo.tempcmd(cmdtext) values(N'
  9460.         from ' + @source_table + N' where ')
  9461. insert into dbo.tempcmd(cmdtext) select procedure_text from #where_clausetab order by c1
  9462. insert into dbo.tempcmd(cmdtext) values(N'
  9463.     end
  9464. ')
  9465.  
  9466. --
  9467. -- insert the conflict row in the publisher cft table
  9468. --
  9469. insert into dbo.tempcmd(cmdtext) values(N'
  9470.     insert into ' + @qualname + N'(')
  9471. insert into dbo.tempcmd(cmdtext) select procedure_text from #valtab order by c1
  9472. insert into dbo.tempcmd(cmdtext) values(N',[qcfttabrowid]) 
  9473.     values (')
  9474. insert into dbo.tempcmd(cmdtext) select procedure_text from #paramtab order by c1
  9475. insert into dbo.tempcmd(cmdtext) values(N',@qcfttabrowid)
  9476. ')
  9477.  
  9478. --
  9479. -- generate compensating command decentralized logging
  9480. -- depending on the number of columns, we will split the compensating
  9481. -- command into several compensating commands
  9482. --
  9483. select @rowcnt = 0, @compinsertabempty = 1
  9484. select @cmd = N'
  9485.     if (@centralized_conflicts = 0)
  9486.     begin
  9487.         select @compcmd = N''insert into ' + master.dbo.fn_MSgensqescstr(@qualname) collate database_default + N' ( '
  9488. insert into dbo.tempcmd(cmdtext) values(@cmd)
  9489.  
  9490. declare #htempcur cursor local for
  9491.     select procedure_text from #valtab order by c1
  9492. for read only
  9493.  
  9494. open #htempcur
  9495. fetch #htempcur into @compinsterm
  9496. while (@@fetch_status = 0)
  9497. begin
  9498.     insert into dbo.tempcmd(cmdtext) select @compinsterm
  9499.     select @rowcnt = @rowcnt + 1
  9500.  
  9501.     --
  9502.     -- if we have processed 10 terms then split the command
  9503.     --
  9504.     if (@rowcnt > 9)
  9505.     begin
  9506.         select @cmd = N'''
  9507.         from ' + @qualname + N' where qcfttabrowid = @qcfttabrowid and tranid = @tranid' 
  9508.         insert into dbo.tempcmd(cmdtext) values(@cmd)        
  9509.     
  9510.         select @cmd = N'
  9511.         exec @retcode = dbo.sp_MSadd_compensating_cmd @subcriber, @subdb, @compcmd, ' 
  9512.             + CAST(@artid as nvarchar(10)) + N', ' + CAST(@pubid as nvarchar(10)) + N',1,0,'
  9513.             + CAST(@compinsertabempty as nvarchar(4)) + N'
  9514.         if (@@error != 0 or @retcode != 0)
  9515.             return 1 
  9516.         
  9517.         select @compcmd = N''' 
  9518.         insert into dbo.tempcmd(cmdtext) values(@cmd)
  9519.         select @rowcnt = 0, @compinsertabempty = 0
  9520.     end
  9521.     fetch #htempcur into @compinsterm
  9522. end
  9523.  
  9524. close #htempcur
  9525. deallocate #htempcur
  9526.  
  9527. insert into dbo.tempcmd(cmdtext) values(N', [qcfttabrowid] ) values ('' ')
  9528. select @rowcnt = @rowcnt + 1
  9529.  
  9530. declare #htempcur cursor local for
  9531.     select procedure_text from #compinstab order by c1
  9532. for read only
  9533.  
  9534. open #htempcur
  9535. fetch #htempcur into @compinsterm
  9536. while (@@fetch_status = 0)
  9537. begin
  9538.     insert into dbo.tempcmd(cmdtext) select @compinsterm
  9539.     select @rowcnt = @rowcnt + 1
  9540.  
  9541.     --
  9542.     -- if we have processed 10 terms then split the command
  9543.     --
  9544.     if (@rowcnt > 9)
  9545.     begin
  9546.         select @cmd = N'
  9547.         from ' + @qualname + N' where qcfttabrowid = @qcfttabrowid and tranid = @tranid' 
  9548.         insert into dbo.tempcmd(cmdtext) values(@cmd)        
  9549.     
  9550.         select @cmd = N'
  9551.         exec @retcode = dbo.sp_MSadd_compensating_cmd @subcriber, @subdb, @compcmd, ' 
  9552.             + CAST(@artid as nvarchar(10)) + N', ' + CAST(@pubid as nvarchar(10)) + N',1,0,'
  9553.             + CAST(@compinsertabempty as nvarchar(4)) + N'
  9554.         if (@@error != 0 or @retcode != 0)
  9555.             return 1 
  9556.         
  9557.         select @compcmd = N'' ''' 
  9558.         insert into dbo.tempcmd(cmdtext) values(@cmd)
  9559.         select @rowcnt = 0, @compinsertabempty = 0
  9560.     end
  9561.     fetch #htempcur into @compinsterm
  9562. end
  9563.  
  9564. close #htempcur
  9565. deallocate #htempcur
  9566.  
  9567. --
  9568. -- script the remaining compensating command
  9569. --
  9570. select @cmd = N' + '', '''''' + CAST([qcfttabrowid] as nvarchar(40)) + '''''''' + N'' ) ''
  9571.         from ' + @qualname + N' where qcfttabrowid = @qcfttabrowid and tranid = @tranid' 
  9572. insert into dbo.tempcmd(cmdtext) values(@cmd)
  9573. select @rowcnt = @rowcnt + 1
  9574.  
  9575. select @cmd = N'
  9576.         exec @retcode = dbo.sp_MSadd_compensating_cmd @subcriber, @subdb, @compcmd, ' 
  9577.             + CAST(@artid as nvarchar(10)) + N', ' + CAST(@pubid as nvarchar(10)) + N',0,0,'
  9578.             + CAST(@compinsertabempty as nvarchar(4)) + N'
  9579.         if (@@error != 0 or @retcode != 0)
  9580.             return 1 ' 
  9581. insert into dbo.tempcmd(cmdtext) values(@cmd)        
  9582. insert into dbo.tempcmd(cmdtext) values(N'
  9583.     end
  9584. end')
  9585.  
  9586. if (@is_debug = 0)
  9587. begin
  9588.     -- Now we select out the command text pieces in proper order so that our caller,
  9589.     -- xp_execresultset will execute the command that creates the stored procedure.
  9590.     select @dbname = db_name()
  9591.     select @cmd = N'select cmdtext from dbo.tempcmd order by c1'
  9592.     exec @retcode = master..xp_execresultset @cmd, @dbname
  9593.     if (@@error != 0 or @retcode != 0)
  9594.     begin
  9595.         -- roll back the tran
  9596.         rollback tran sp_MSmaketrancftproc
  9597.         return (1)
  9598.     end
  9599.     
  9600.     --
  9601.     -- Check if we create the proc and update sysarticleupdates
  9602.     --
  9603.     select @conflict_proc_id = id from sysobjects where name = @procname and type = 'P '
  9604.     if (@conflict_proc_id is NULL or @conflict_proc_id = 0)
  9605.     begin
  9606.         -- roll back the tran
  9607.         rollback tran sp_MSmaketrancftproc
  9608.         return (1)
  9609.     end
  9610.     else
  9611.     begin
  9612.         update dbo.sysarticleupdates set ins_conflict_proc = @conflict_proc_id
  9613.             where artid = @artid and pubid = @pubid
  9614.         if @@error <> 0
  9615.         begin
  9616.             -- roll back the tran
  9617.             rollback tran sp_MSmaketrancftproc
  9618.             return (1)
  9619.         end
  9620.  
  9621.         -- mark the proc as system object
  9622.         if (@owner in ('dbo','INFORMATION_SCHEMA'))
  9623.         begin
  9624.             exec @retcode = dbo.sp_MS_marksystemobject @procname
  9625.             if (@@error != 0 or @retcode != 0)
  9626.             begin
  9627.                 -- roll back the tran
  9628.                 rollback tran sp_MSmaketrancftproc
  9629.                 return (1)
  9630.             end
  9631.         end
  9632.     end
  9633. end
  9634. else
  9635.     select cmdtext from dbo.tempcmd order by c1
  9636.  
  9637. COMMIT TRAN 
  9638.  
  9639. -- drop the temp tables
  9640. drop table dbo.tempcmd
  9641. drop table #argtab 
  9642. drop table #valtab 
  9643. drop table #paramtab 
  9644. drop table #seltab 
  9645. drop table #sel2tab 
  9646. drop table #decltab 
  9647. drop table #assigntab 
  9648. drop table #where_clausetab 
  9649. drop table #compinstab
  9650. END
  9651. go
  9652.  
  9653. exec dbo.sp_MS_marksystemobject sp_MSmaketrancftproc 
  9654. go
  9655.  
  9656. print ''
  9657. print 'Creating procedure sp_changesubstatus'
  9658. go
  9659. CREATE PROCEDURE sp_changesubstatus (
  9660.     @publication sysname = '%',    /* publication name */
  9661.     @article sysname = '%',        /* article name */
  9662.     @subscriber sysname = '%',      /* subscriber name */
  9663.     @status sysname,                /* subscription status */
  9664.     @previous_status sysname=NULL,  /* previous subscription status */
  9665.     @destination_db sysname = '%',   /* destination database name */
  9666.  
  9667.     @frequency_type int = NULL,
  9668.     @frequency_interval int = NULL,
  9669.     @frequency_relative_interval int = NULL,
  9670.     @frequency_recurrence_factor int = NULL,
  9671.     @frequency_subday int = NULL,
  9672.     @frequency_subday_interval int = NULL,
  9673.     @active_start_time_of_day int = NULL,
  9674.     @active_end_time_of_day int = NULL,
  9675.     @active_start_date int = NULL,
  9676.     @active_end_date int = NULL,
  9677.     @optional_command_line nvarchar(4000) = NULL,
  9678.     @distribution_jobid binary(16) = NULL OUTPUT,
  9679.     @from_auto_sync bit = 0,
  9680.     @ignore_distributor bit = 0,
  9681.     -- Agent offload
  9682.     @offloadagent bit = 0,
  9683.     @offloadserver sysname = NULL,
  9684.     @dts_package_name sysname = NULL,
  9685.     @dts_package_password nvarchar(524) = NULL,
  9686.     @dts_package_location int = 0,
  9687.     @schemastabilityonly int = 0,
  9688.     @distribution_job_name sysname = NULL
  9689.  
  9690. ) AS
  9691.  
  9692.     SET NOCOUNT ON
  9693.     DECLARE @inactive tinyint
  9694.     DECLARE @subscribed tinyint
  9695.     DECLARE @active tinyint
  9696.     DECLARE @initiated tinyint
  9697.     DECLARE @public tinyint
  9698.     DECLARE @replicate_bit smallint
  9699.     DECLARE @msg nvarchar(255)
  9700.     DECLARE @prevstatid tinyint
  9701.     DECLARE @artid int
  9702.     DECLARE @tabid int
  9703.     DECLARE @srvid smallint
  9704.     DECLARE @statusid tinyint
  9705.     DECLARE @distributor sysname
  9706.     DECLARE @distribdb sysname
  9707.     DECLARE @distproc nvarchar (255)
  9708.     DECLARE @pub_db sysname
  9709.     DECLARE @dest_db sysname
  9710.     DECLARE @sub_name sysname
  9711.     DECLARE @sub_status tinyint
  9712.     DECLARE @sub_ts varbinary (16)
  9713.     DECLARE @non_sql_flag bit
  9714.     DECLARE @qcmd nvarchar (4000)
  9715.     DECLARE @cmd1 nvarchar (255)
  9716.     DECLARE @cmd2 nvarchar (255)
  9717.     DECLARE @cmd3 nvarchar (255)
  9718.     DECLARE @retcode int
  9719.     DECLARE @repl_freq tinyint
  9720.     DECLARE @art_type tinyint
  9721.     DECLARE @proccmd  nvarchar(255)
  9722.     DECLARE @procnum  smallint
  9723.     DECLARE @finished_real bit
  9724.     DECLARE @finished_virtual bit
  9725.     DECLARE @virtual_id smallint
  9726.     DECLARE @immediate_sync bit
  9727.     DECLARE @enabled_for_internet bit
  9728.     DECLARE @allow_anonymous bit
  9729.     DECLARE @subscription_type int
  9730.     DECLARE @xact_seqno binary(10)
  9731.     DECLARE @sync_type tinyint
  9732.     DECLARE @automatic tinyint
  9733.  
  9734.     DECLARE @art_change bit
  9735.     declare @login_name sysname
  9736.  
  9737.     DECLARE @pubid int
  9738.     DECLARE @syncinit_lsn binary(10)
  9739.  
  9740.     DECLARE @f_syncstat_posted bit
  9741.  
  9742.     -- synctran
  9743.     DECLARE @update_mode tinyint
  9744.     DECLARE @art_name sysname
  9745.     declare @synctran tinyint
  9746.     declare @no_distproc bit
  9747.     declare @loopback_detection bit
  9748.     
  9749.     /*
  9750.     ** Initializations.
  9751.     */
  9752.     select @synctran = 1
  9753.             
  9754.     SELECT @automatic = 1
  9755.     SELECT @inactive = 0        /* Const: subscription status 'inactive' */
  9756.     SELECT @subscribed = 1      /* Const: subscription status 'subscribed' */
  9757.     SELECT @active = 2          /* Const: subscription status 'active' */
  9758.     SELECT @initiated = 3        /* Const: subscription status 'initiated' */
  9759.     SELECT @public = 0          /* Const: publication status 'public' */
  9760.     SELECT @pub_db = DB_NAME()
  9761.     SELECT @virtual_id = -1
  9762.     SELECT @art_change = 0
  9763.  
  9764.     SELECT @f_syncstat_posted = 0
  9765.  
  9766.     SELECT @replicate_bit = 2
  9767.  
  9768.     /* 
  9769.     ** Security Check.
  9770.     ** We use login_name stored in syssubscriptions to manage security 
  9771.     */
  9772.  
  9773.     /*
  9774.     ** Parameter Check:  @publication
  9775.     ** Check to make sure that the publication exists, that it's not NULL,
  9776.     ** and that it conforms to the rules for identifiers.
  9777.     */
  9778.  
  9779.     IF @publication IS NULL
  9780.         BEGIN
  9781.             RAISERROR (14043, 16, -1, '@publication')
  9782.             RETURN (1)
  9783.         END
  9784.  
  9785.     IF @publication <> '%'
  9786.         BEGIN
  9787.             EXECUTE @retcode = dbo.sp_validname @publication
  9788.             IF @@ERROR <> 0 OR @retcode <> 0
  9789.             RETURN (1)
  9790.         END
  9791.  
  9792.     IF NOT EXISTS (SELECT * FROM syspublications WHERE name LIKE @publication)
  9793.         BEGIN
  9794.         IF @publication = '%'
  9795.                 RAISERROR (14008, 11, -1)
  9796.         ELSE
  9797.                 RAISERROR (20026, 11, -1, @publication)
  9798.         RETURN (1)
  9799.         END
  9800.  
  9801.     /*
  9802.     ** Parameter Check:  @article
  9803.     ** Check to make sure that the article exists, that it's not null,
  9804.     ** and that it conforms to the rules for identifiers.
  9805.     */
  9806.  
  9807.     IF @article IS NULL
  9808.         BEGIN
  9809.             RAISERROR (14043, 16, -1, '@article')
  9810.             RETURN (1)
  9811.         END
  9812.  
  9813.     /*
  9814.     IF @article <> '%'
  9815.         BEGIN
  9816.             EXECUTE @retcode = dbo.sp_validname @article
  9817.             IF @@ERROR <> 0 OR @retcode <> 0
  9818.             RETURN (1)
  9819.         END
  9820.     */
  9821.  
  9822.     IF NOT EXISTS (SELECT *
  9823.                      FROM sysextendedarticlesview a,
  9824.                           syspublications b
  9825.                 WHERE a.name LIKE @article
  9826.                       AND a.pubid = b.pubid
  9827.                       AND b.name LIKE @publication)
  9828.  
  9829.         BEGIN
  9830.         IF @article = '%'
  9831.                 RAISERROR (14009, 11, -1, @publication)
  9832.         ELSE
  9833.                 RAISERROR (20027, 11, -1, @article)
  9834.         RETURN (1)
  9835.         END
  9836.  
  9837.     /*
  9838.     ** Parameter Check:  @subscriber
  9839.     ** Check to make sure that the subscriber exists, that it is not NULL,
  9840.     ** and that it conforms to the rules for identifiers.
  9841.     ** Null subscriber represents virtual subscriptions
  9842.     */
  9843.  
  9844.     IF @subscriber IS NOT NULL AND @subscriber <> '%'
  9845.     BEGIN    
  9846.         EXECUTE @retcode = dbo.sp_validname @subscriber
  9847.         IF @@ERROR <> 0 OR @retcode <> 0
  9848.         RETURN (1)
  9849.  
  9850.         IF NOT EXISTS (SELECT *
  9851.                          FROM master..sysservers
  9852.                         WHERE UPPER(srvname) = UPPER(@subscriber) collate database_default
  9853.                           AND (srvstatus & 4) <> 0)
  9854.  
  9855.             BEGIN
  9856.                 RAISERROR (14063, 11, -1)
  9857.                 RETURN (1)
  9858.             END
  9859.     END
  9860.  
  9861.     /*
  9862.     ** Parameter Check: @status.
  9863.     ** Set the @statusid according to the @status value.  Values can be
  9864.     ** any of the following:
  9865.     **
  9866.     **      status      statusid
  9867.     **      =========   ========
  9868.     **      inactive           0
  9869.     **      subscribed         1
  9870.     **      active             2
  9871.     **        initiated          3
  9872.     */
  9873.  
  9874.     IF LOWER(@status) NOT IN ('active', 'subscribed', 'inactive', 'initiated')
  9875.         BEGIN
  9876.             RAISERROR (14065, 16, -1)
  9877.         RETURN (1)
  9878.         END
  9879.  
  9880.     IF LOWER(@status) IN ('initiated')
  9881.         SELECT @statusid = @initiated
  9882.     ELSE IF LOWER(@status) IN ('active')
  9883.         SELECT @statusid = @active
  9884.     ELSE IF LOWER(@status) IN ('subscribed')
  9885.         SELECT @statusid = @subscribed
  9886.     ELSE
  9887.         SELECT @statusid = @inactive
  9888.  
  9889.     /*
  9890.     ** Parameter Check: @previous_status.
  9891.     ** Set the @prevstatid according to the @previous_status value.
  9892.     ** Values can be any of the following:
  9893.     **
  9894.     **      previous_status      prevstatid
  9895.     **      ===============      ==========
  9896.     **      inactive                      0
  9897.     **      subscribed                    1
  9898.     **      active                        2
  9899.     **        initiated                      3
  9900.     */
  9901.  
  9902.     IF @previous_status IS NOT NULL
  9903.     BEGIN
  9904.         IF LOWER(@previous_status) NOT IN ('initiated','active', 'subscribed', 'inactive')
  9905.         BEGIN
  9906.             RAISERROR (14066, 16, -1)
  9907.             RETURN (1)
  9908.         END
  9909.  
  9910.         IF LOWER(@status) = LOWER(@previous_status)
  9911.         BEGIN
  9912.             RAISERROR (14067, 16, -1)
  9913.             RETURN (1)
  9914.         END
  9915.  
  9916.         IF LOWER(@previous_status) IN ('initiated')
  9917.             SELECT @prevstatid = @initiated
  9918.         ELSE IF LOWER(@previous_status) IN ('active')
  9919.             SELECT @prevstatid = @active
  9920.         ELSE IF LOWER(@previous_status) IN ('subscribed')
  9921.             SELECT @prevstatid = @subscribed
  9922.         ELSE
  9923.            SELECT @prevstatid = @inactive
  9924.     END
  9925.  
  9926.     /*
  9927.     ** Parameter Check: @destination_db.
  9928.     ** Set @destination_db to current database if not specified.  Make
  9929.     ** sure that the @destination_db conforms to the rules for identifiers.
  9930.     */
  9931.  
  9932.     IF @destination_db <> '%' 
  9933.     BEGIN
  9934.         EXECUTE @retcode = dbo.sp_validname @destination_db
  9935.         IF @retcode <> 0
  9936.         RETURN (1)
  9937.     END
  9938.  
  9939.     /*
  9940.     ** Get distribution server information for remote RPC
  9941.     ** subscription calls.
  9942.     ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
  9943.     */
  9944.     if @ignore_distributor = 1 
  9945.         select @no_distproc = 1
  9946.     else
  9947.         select @no_distproc = 0
  9948.  
  9949.     IF @no_distproc = 0 --and @from_auto_sync = 0 
  9950.     BEGIN
  9951.         EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  9952.                                            @distribdb = @distribdb OUTPUT
  9953.  
  9954.         IF @@ERROR <> 0
  9955.         BEGIN
  9956.             RAISERROR (14071, 16, -1)
  9957.             RETURN (1)
  9958.         END
  9959.  
  9960.         IF @retcode <> 0 OR @distribdb IS NULL OR @distributor IS NULL
  9961.         BEGIN
  9962.             RAISERROR (14071, 16, -1)
  9963.             RETURN (1)
  9964.         END
  9965.     END
  9966.  
  9967.  
  9968.     create table #sysextendedarticlesview
  9969.     (
  9970.     artid               int                 NULL,
  9971.     columns             varbinary(32)       NULL,
  9972.     creation_script     nvarchar(255)       collate database_default null,
  9973.     del_cmd             nvarchar(255)       collate database_default null,
  9974.     description         nvarchar(255)       collate database_default null,
  9975.     dest_table          sysname             collate database_default null,
  9976.     filter              int                 NULL,
  9977.     filter_clause       ntext               NULL,
  9978.     ins_cmd             nvarchar(255)       collate database_default null,
  9979.     name                sysname             collate database_default null,
  9980.     objid               int                 NULL,
  9981.     pubid               int                 NULL,
  9982.     pre_creation_cmd    tinyint             NULL,
  9983.     status              tinyint             NULL,
  9984.     sync_objid          int                 NULL,
  9985.     type                tinyint             NULL,
  9986.     upd_cmd             nvarchar(255)       collate database_default null,
  9987.     schema_option       binary(8)           NULL,
  9988.     dest_owner          sysname             collate database_default null
  9989.     )
  9990.  
  9991.     insert into #sysextendedarticlesview select * from sysextendedarticlesview
  9992.  
  9993.     begin tran
  9994.     save TRANSACTION changesubstatus
  9995.  
  9996.         SELECT @finished_virtual = 0
  9997.         SELECT @finished_real = 0
  9998.  
  9999.         /* 
  10000.         ** If @subscriber is null, don't process real subscriptions
  10001.         ** If @subscriber is not null and '%', don't process virtual subscriptions
  10002.         */
  10003.         IF @subscriber IS NULL SELECT @finished_real = 1
  10004.         ELSE IF @subscriber <> '%'  SELECT @finished_virtual = 1
  10005.  
  10006.         WHILE (@finished_real = 0 OR @finished_virtual = 0)
  10007.         BEGIN
  10008.             /*
  10009.             ** Declare cursor containing subscriptions to be updated.
  10010.             */
  10011.             IF @finished_real = 0
  10012.             BEGIN
  10013.                 IF @previous_status IS NOT NULL
  10014.                 BEGIN
  10015.                     DECLARE hCsubstatus CURSOR LOCAL SCROLL_LOCKS FOR
  10016.                         SELECT sub.artid,
  10017.                                art.objid,
  10018.                                sub.srvid,
  10019.                                ss.srvname,
  10020.                                sub.dest_db,
  10021.                                sub.status,
  10022.                            case when ss.srvproduct = 'MSREPL-NONSQL' or
  10023.                                 pub.allow_dts = 1
  10024.                                 then 1
  10025.                            else 0 end,
  10026.                            pub.repl_freq,
  10027.                                art.type,
  10028.                            pub.immediate_sync,
  10029.                            pub.enabled_for_internet,
  10030.                            pub.allow_anonymous,
  10031.                            sub.subscription_type,
  10032.                            sub.sync_type,
  10033.                            sub.update_mode,
  10034.                            art.name,
  10035.                            sub.login_name,
  10036.                            sub.loopback_detection,
  10037.                            pub.pubid
  10038.                           FROM syssubscriptions sub,
  10039.                                #sysextendedarticlesview art,
  10040.                                syspublications pub,
  10041.                                master..sysservers ss
  10042.                          WHERE pub.name LIKE @publication collate database_default
  10043.                            AND art.name LIKE @article collate database_default
  10044.                            AND ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber) collate database_default))
  10045.                            AND sub.srvid = ss.srvid
  10046.                            AND sub.artid = art.artid
  10047.                            AND art.pubid = pub.pubid
  10048.                            AND sub.status = @prevstatid
  10049.                            AND ((@destination_db = N'%') OR (sub.dest_db = @destination_db collate database_default))
  10050.                 END
  10051.                 ELSE
  10052.                 BEGIN
  10053.                     DECLARE hCsubstatus CURSOR LOCAL SCROLL_LOCKS FOR
  10054.                         SELECT sub.artid,
  10055.                                art.objid,
  10056.                                sub.srvid,
  10057.                                ss.srvname,
  10058.                                sub.dest_db,
  10059.                                sub.status,
  10060.                            case when ss.srvproduct = 'MSREPL-NONSQL' or
  10061.                                 pub.allow_dts = 1
  10062.                                 then 1
  10063.                            else 0 end,
  10064.                            pub.repl_freq,
  10065.                                art.type,
  10066.                            pub.immediate_sync,
  10067.                            pub.enabled_for_internet,
  10068.                            pub.allow_anonymous,
  10069.                            sub.subscription_type,
  10070.                            sub.sync_type,
  10071.                            sub.update_mode,
  10072.                            art.name,
  10073.                            sub.login_name,
  10074.                            sub.loopback_detection,
  10075.                            pub.pubid
  10076.                           FROM syssubscriptions sub,
  10077.                                #sysextendedarticlesview art,
  10078.                                syspublications pub,
  10079.                                master..sysservers ss
  10080.                          WHERE pub.name LIKE @publication collate database_default
  10081.                            AND art.name LIKE @article collate database_default
  10082.                            AND ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber) collate database_default))
  10083.                            AND sub.srvid = ss.srvid
  10084.                            AND sub.artid = art.artid
  10085.                            AND art.pubid = pub.pubid
  10086.                            AND ((@destination_db = N'%') OR (sub.dest_db = @destination_db))
  10087.                 END           
  10088.                 SELECT @finished_real = 1
  10089.             END
  10090.  
  10091.             ELSE IF @finished_virtual = 0  
  10092.             BEGIN
  10093.                 DECLARE @sub_bit smallint
  10094.                 DECLARE @null_name sysname
  10095.  
  10096.                 SELECT @sub_bit = 4
  10097.                 SELECT @null_name = NULL
  10098.  
  10099.                 /*
  10100.                 ** Treat anonymous virtual subscription as DSN subscriber.
  10101.                 ** This will cause sp_MSarticlecol being called in sp_changesubstatus
  10102.                 */
  10103.                 DECLARE hCsubstatus CURSOR LOCAL SCROLL_LOCKS FOR
  10104.                     SELECT sub.artid,
  10105.                            art.objid,
  10106.                            sub.srvid,
  10107.                            @null_name,              /* subscriber name. NULL for virtual */
  10108.                            sub.dest_db,
  10109.                            sub.status,
  10110.                        case when pub.allow_anonymous = 1 or
  10111.                             pub.allow_dts = 1 then 1
  10112.                        else 0 end, /*indicate dsn or not */ 
  10113.                        pub.repl_freq,
  10114.                        art.type,
  10115.                        pub.immediate_sync,
  10116.                        pub.enabled_for_internet,
  10117.                        pub.allow_anonymous,
  10118.                        sub.subscription_type,
  10119.                        sub.sync_type,
  10120.                        sub.update_mode,
  10121.                        art.name,
  10122.                        login_name,
  10123.                        sub.loopback_detection,
  10124.                        pub.pubid
  10125.  
  10126.                       FROM syssubscriptions sub,
  10127.                            #sysextendedarticlesview art,
  10128.                            syspublications pub
  10129.                      WHERE pub.name LIKE @publication
  10130.                        AND art.name LIKE @article
  10131.                        AND sub.srvid = -1
  10132.                        AND sub.artid = art.artid
  10133.                        AND art.pubid = pub.pubid
  10134.                 SELECT @finished_virtual = 1
  10135.             END
  10136.  
  10137.             OPEN hCsubstatus
  10138.             FETCH hCsubstatus INTO @artid, @tabid, @srvid, @sub_name, @dest_db,
  10139.                 @sub_status, @non_sql_flag, @repl_freq, @art_type,
  10140.                 @immediate_sync, @enabled_for_internet,
  10141.                 @allow_anonymous, @subscription_type, @sync_type, @update_mode,
  10142.                 @art_name, @login_name, @loopback_detection,@pubid
  10143.  
  10144.  
  10145.             WHILE (@@fetch_status <> -1)
  10146.             BEGIN
  10147.  
  10148.                 IF  suser_sname(suser_sid()) <> @login_name AND is_srvrolemember('sysadmin') <> 1  
  10149.                     AND is_member ('db_owner') <> 1
  10150.                 BEGIN
  10151.                         RAISERROR (14126, 11, -1)
  10152.                         RETURN (1)
  10153.                 END
  10154.                 /*
  10155.                 ** condition 1:
  10156.                 ** If current status is same as new status, and status is not 'initiated' do nothing.
  10157.                 ** If both old and new status = 'initiated', this indicates that the 
  10158.                 ** snapshot agent previously bombed out between the initiation and activation stages and
  10159.                 ** is now again trying to sync the publication.
  10160.                 **
  10161.                 ** condition 2:
  10162.                 ** @auto_sync_only is used by snapshot for immediate_sync
  10163.                 ** publications.
  10164.                 **
  10165.                 ** condition 3:
  10166.                 ** Because sp_MSactivate_auto_sub (and thus the snapshot agent)
  10167.                 ** calls this procedure for all subscriptions, we need to ignore
  10168.                 ** the real subscriptions that are already active so that they won't be
  10169.                 ** transitioned to the initiated state.  If we don't do this, those
  10170.                 ** subscriptions will be resynced using the new snapshot.
  10171.                 ** 
  10172.                 ** however, we DO want a new snapshot to be generated for virtual
  10173.                 ** subscriptions to active publications.
  10174.                 **
  10175.                 */
  10176.                 IF  (@sub_status = @statusid AND @sub_status <> @initiated ) OR
  10177.                     (@from_auto_sync = 1 AND @sync_type <> @automatic) OR
  10178.                     (@sub_status = @active AND @statusid = @initiated AND @srvid <> -1 AND @from_auto_sync = 1)
  10179.                 BEGIN
  10180.                     FETCH hCsubstatus INTO @artid, @tabid, @srvid, @sub_name,
  10181.                        @dest_db, @sub_status, @non_sql_flag, @repl_freq, @art_type, 
  10182.                        @immediate_sync, @enabled_for_internet,
  10183.                        @allow_anonymous, @subscription_type, @sync_type, @update_mode,
  10184.                        @art_name, @login_name, @loopback_detection, @pubid
  10185.  
  10186.                     CONTINUE
  10187.                 END
  10188.  
  10189.                 -- If changing a virtual subscription to 'subscribed' status
  10190.                 -- change the immediate_sync_ready bit
  10191.                 if @statusid = @subscribed and @sub_name is NULL
  10192.                 begin
  10193.                     UPDATE syspublications SET immediate_sync_ready = 0 WHERE 
  10194.                         pubid = @pubid and
  10195.                         immediate_sync_ready <> 0
  10196.                     IF @@ERROR <> 0
  10197.                     BEGIN
  10198.                       CLOSE hCsubstatus
  10199.                       DEALLOCATE hCsubstatus
  10200.                       if @@trancount > 0
  10201.                         begin
  10202.                             ROLLBACK TRANSACTION changesubstatus
  10203.                             commit tran
  10204.                         end
  10205.                       RETURN (1)
  10206.                     END
  10207.                 end
  10208.  
  10209.  
  10210.                 -- acquire schema lock, mark rollback point in order to allow
  10211.                 -- for 'unflush' of proc cache
  10212.  
  10213.                 declare @qualified_name nvarchar(512)
  10214.  
  10215.                 exec dbo.sp_MSget_qualified_name @tabid, @qualified_name output
  10216.                 exec dbo.sp_replupdateschema @qualified_name, @schemastabilityonly
  10217.  
  10218.                 /*
  10219.                 ** Update syssubscription status
  10220.                 */
  10221.                 UPDATE syssubscriptions
  10222.                        SET status = @statusid
  10223.                        FROM syssubscriptions sub,
  10224.                            sysextendedarticlesview art,
  10225.                            syspublications pub
  10226.                        WHERE pub.name LIKE @publication
  10227.                             AND art.artid = @artid
  10228.                             AND sub.srvid = @srvid
  10229.                             AND sub.artid = @artid
  10230.                             AND art.pubid = pub.pubid
  10231.                             AND sub.dest_db = @dest_db
  10232.                 if @@ERROR <> 0
  10233.                                BEGIN
  10234.                                CLOSE hCsubstatus
  10235.                                DEALLOCATE hCsubstatus
  10236.                                 if @@trancount > 0
  10237.                                 begin
  10238.                                     ROLLBACK TRANSACTION changesubstatus
  10239.                                     commit tran
  10240.                                 end
  10241.                                 RAISERROR (14053, 16, -1)
  10242.                                    RETURN (1)
  10243.                                END
  10244.  
  10245.                 --
  10246.                 -- Subscription reinitialization processing for Immediate 
  10247.                 -- and Queued publications
  10248.                 --
  10249.                 if (@update_mode in (1,2,3,4,5))
  10250.                 begin
  10251.                     select @retcode = 0
  10252.                     IF ((@statusid != @active) AND (@sub_status = @active))
  10253.                     begin
  10254.                         --
  10255.                         -- If we are going from active state to subscribed
  10256.                         -- set the reinit column so that no more updates from
  10257.                         -- subscriber are applied until (re)activation
  10258.                         --
  10259.                         update dbo.syssubscriptions
  10260.                         set queued_reinit = 1
  10261.                         where 
  10262.                             artid = @artid 
  10263.                             and srvid = @srvid
  10264.                             and dest_db = @dest_db
  10265.                     end
  10266.                     ELSE IF ((@statusid = @active) AND (@sub_status != @active ))
  10267.                     begin
  10268.                         --
  10269.                         -- If we are going from subscribed state to active state
  10270.                         --
  10271.                         if (@update_mode = 1)
  10272.                         begin
  10273.                             --
  10274.                             -- Sync tran case : reset the reinit column
  10275.                             --
  10276.                             update dbo.syssubscriptions
  10277.                             set queued_reinit = 0
  10278.                             where 
  10279.                                 artid = @artid 
  10280.                                 and srvid = @srvid
  10281.                                 and dest_db = @dest_db
  10282.                         end
  10283.  
  10284.                         --
  10285.                         -- For queued case : we do not need to send compensating
  10286.                         -- command anymore, sp_addqueued_artinfo will do the 
  10287.                         -- queue reinitialization for all types of queued
  10288.                         -- subscriptions
  10289.                         --
  10290.  
  10291.                         /**********
  10292.                         else
  10293.                         begin
  10294.                             -- 
  10295.                             -- Queued case : send a compensating action command to 
  10296.                             -- subscriber to reinitialize its queue
  10297.                             --
  10298.                             select @qcmd = N'exec sp_MSreset_queue ''' + @@servername + '''' + 
  10299.                                 ', ''' + db_name() + '''' +
  10300.                                 ', ''' + name + '''' +
  10301.                                 ', ' + cast(@artid as nvarchar(8))
  10302.                             from syspublications
  10303.                             where pubid = @pubid
  10304.                                                       
  10305.                             exec @retcode = dbo.sp_MSadd_compensating_cmd
  10306.                                 @orig_srv = @sub_name
  10307.                                 ,@orig_db = @dest_db
  10308.                                 ,@command = @qcmd
  10309.                                 ,@article_id = @artid 
  10310.                                 ,@publication_id = @pubid
  10311.                         end
  10312.                         **********/
  10313.                     end                    
  10314.  
  10315.                     --
  10316.                     -- Check for error
  10317.                     --
  10318.                     if (@@error != 0 or @retcode != 0)
  10319.                     begin
  10320.                         CLOSE hCsubstatus
  10321.                         DEALLOCATE hCsubstatus
  10322.                         if @@trancount > 0
  10323.                         begin
  10324.                             ROLLBACK TRANSACTION changesubstatus
  10325.                             commit tran
  10326.                         end
  10327.                         RAISERROR (14053, 16, -1)
  10328.                         RETURN (1)
  10329.                     end
  10330.                 end
  10331.  
  10332.                 /*
  10333.                 ** Get timestamp of subscription.
  10334.                 */
  10335.                 EXEC @retcode = dbo.sp_replincrementlsn @xact_seqno OUTPUT
  10336.                 IF @@ERROR <> 0 or @retcode <> 0
  10337.                             BEGIN
  10338.                                CLOSE hCsubstatus
  10339.                                DEALLOCATE hCsubstatus
  10340.                                if @@trancount > 0
  10341.                                 begin
  10342.                                     ROLLBACK TRANSACTION changesubstatus
  10343.                                     commit tran
  10344.                                 end
  10345.                                RETURN (1)
  10346.                             END
  10347.                 select @sub_ts = @xact_seqno
  10348.  
  10349.  
  10350.                 IF @sub_ts IS NULL
  10351.                             BEGIN
  10352.                                CLOSE hCsubstatus
  10353.                                DEALLOCATE hCsubstatus
  10354.                                if @@trancount > 0
  10355.                                 begin
  10356.                                     ROLLBACK TRANSACTION changesubstatus
  10357.                                     commit tran
  10358.                                 end
  10359.                                 RAISERROR (14053, 16, -1)
  10360.                                RETURN (1)
  10361.                             END
  10362.                 
  10363.                 -------------------------------------------------------------------
  10364.                 -- If initiating the subscription, toss a SYNCINIT token into the 
  10365.                 -- log for the article and return LSN as a results set
  10366.                 --
  10367.                 -- Note:  This should come after the subscription LSN is obtained.
  10368.                 -- in order to assure proper application of SYNSTAT tokens in the
  10369.                 -- distribution database
  10370.                 -------------------------------------------------------------------
  10371.  
  10372.                 IF @statusid = @initiated --and @sub_status <> @initiated
  10373.                 BEGIN
  10374.                     -- set filtered status.  Must log old text information during initiated state
  10375.                     -- in order to support update splitting
  10376.  
  10377.                     exec sp_MSsetfilteredstatus @tabid
  10378.  
  10379.                     -- set nonsqlsub status.  must prevent UPDATETEXT operations during
  10380.                     -- initiated state
  10381.  
  10382.                     exec sp_MSarticlecol @artid, NULL,N'nonsqlsub', N'add'
  10383.                     exec sp_replpostsyncstatus @pubid, @artid, 1, @syncinit_lsn output
  10384.                     if @f_syncstat_posted = 0
  10385.                     begin
  10386.                         select @pubid, @artid, @syncinit_lsn
  10387.                         select @f_syncstat_posted = 1
  10388.                     end
  10389.                 END
  10390.  
  10391.                 -------------------------------------------------------------------
  10392.                 -- If changing the state FROM initiated, post a SYNCDONE token to the 
  10393.                 -- log for the article. 
  10394.                 -------------------------------------------------------------------
  10395.                 IF @sub_status = @initiated and @statusid <> @initiated
  10396.                 BEGIN
  10397.                     -- reset filtered status to normal value
  10398.  
  10399.                     exec sp_MSsetfilteredstatus @tabid
  10400.  
  10401.                     -- clear nonsqlsub status for this article.
  10402.  
  10403.                     exec sp_MSarticlecol @artid, NULL,N'nonsqlsub', N'drop'
  10404.  
  10405.                     --if @f_syncstat_posted = 0
  10406.                     --begin
  10407.                         exec sp_replpostsyncstatus @pubid, @artid, 0, @syncinit_lsn output
  10408.                     --    select @f_syncstat_posted = 1
  10409.                     --end
  10410.                 END
  10411.  
  10412.                 /*
  10413.                 ** If activating subscription, update sysextendedarticlesview, sysobjects and
  10414.                 ** MSrepl_subscriptions.
  10415.                 */
  10416.                 IF @statusid in ( @active, @initiated )
  10417.                 BEGIN
  10418.                     
  10419.                     /*
  10420.                     ** Update status of article to show it has been activated.
  10421.                     */
  10422.                     IF @repl_freq = 0 and EXISTS (SELECT * FROM sysextendedarticlesview WHERE artid = @artid
  10423.                         AND status & 1 <> 1)
  10424.                     BEGIN
  10425.                         -- At most one row will be updated in the following two updates as the artid is unique
  10426.                         -- among both sysarticles and sysschemaarticles
  10427.                         UPDATE sysarticles SET status = status | 1 WHERE artid = @artid
  10428.                         IF @@ERROR <> 0
  10429.                             BEGIN
  10430.                                 CLOSE hCsubstatus
  10431.                                 DEALLOCATE hCsubstatus
  10432.                                 if @@trancount > 0
  10433.                                 begin
  10434.                                     ROLLBACK TRANSACTION changesubstatus
  10435.                                     commit tran
  10436.                                 end
  10437.                                 RAISERROR (14069, 16, -1)
  10438.                                 RETURN (1)
  10439.                             END
  10440.                         UPDATE sysschemaarticles SET status = status | 1 WHERE artid = @artid
  10441.                         IF @@ERROR <> 0
  10442.                             BEGIN
  10443.                                 CLOSE hCsubstatus
  10444.                                 DEALLOCATE hCsubstatus
  10445.                                 if @@trancount > 0
  10446.                                 begin
  10447.                                     ROLLBACK TRANSACTION changesubstatus
  10448.                                     commit tran
  10449.                                 end
  10450.                                 RAISERROR (14069, 16, -1)
  10451.                                 RETURN (1)
  10452.                             END
  10453.                         SELECT @art_change = 1
  10454.                     END
  10455.  
  10456.                         /*
  10457.                         ** Turn the replication flag on for this object in the
  10458.                         ** sysobjects table (make it logbased).
  10459.                         */
  10460.  
  10461.                     if @repl_freq = 0
  10462.                       BEGIN
  10463.                         UPDATE sysobjects SET replinfo = replinfo | @replicate_bit
  10464.                         WHERE id = ( SELECT objid FROM sysextendedarticlesview WHERE artid = @artid )
  10465.                       END
  10466.  
  10467.                       IF @@ERROR <> 0
  10468.                       BEGIN
  10469.                           CLOSE hCsubstatus
  10470.                           DEALLOCATE hCsubstatus
  10471.                           if @@trancount > 0
  10472.                             begin
  10473.                                 ROLLBACK TRANSACTION changesubstatus
  10474.                                 commit tran
  10475.                             end
  10476.                           RAISERROR (14068, 16, -1)
  10477.                           RETURN (1)
  10478.                       END
  10479.  
  10480.                 END
  10481.  
  10482.                 /*
  10483.                 ** Update status of all columns if subscriber is non-SQL Server.
  10484.                 */
  10485.                 IF @non_sql_flag <> 0 AND ( @art_type & 1 ) = 1
  10486.                 BEGIN
  10487.                     IF @statusid = @subscribed OR @statusid = @active
  10488.                     BEGIN
  10489.  
  10490.                         EXEC @retcode = dbo.sp_MSarticlecol @artid, NULL,
  10491.                                                           'nonsqlsub', 'add'
  10492.                         IF @@ERROR <> 0 OR @retcode <> 0
  10493.                         BEGIN
  10494.                             CLOSE hCsubstatus
  10495.                             DEALLOCATE hCsubstatus
  10496.                             if @@trancount > 0
  10497.                             begin
  10498.                                 ROLLBACK TRANSACTION changesubstatus
  10499.                                 commit tran
  10500.                             end
  10501.                             RAISERROR (14068, 16, -1)
  10502.                             RETURN (1)
  10503.                         END
  10504.  
  10505.  
  10506.                     END
  10507.                     ELSE IF @statusid = @inactive
  10508.                     BEGIN
  10509.  
  10510.                         EXEC @retcode = dbo.sp_MSarticlecol @artid, NULL,
  10511.                                                           'nonsqlsub', 'drop'
  10512.                         IF @@ERROR <> 0 OR @retcode <> 0
  10513.                         BEGIN
  10514.                           CLOSE hCsubstatus
  10515.                           DEALLOCATE hCsubstatus
  10516.                           if @@trancount > 0
  10517.                             begin
  10518.                                 ROLLBACK TRANSACTION changesubstatus
  10519.                                 commit tran
  10520.                             end
  10521.                           RAISERROR (14068, 16, -1)
  10522.                           RETURN (1)
  10523.                         END
  10524.                     END
  10525.                 END
  10526.  
  10527.                 
  10528.                 /*
  10529.                 ** If deactivating subscription, update sysextendedarticlesview, sysobjects and
  10530.                 ** MSrepl_subscriptions.
  10531.                 */
  10532.  
  10533.                 IF @statusid NOT IN( @active, @initiated ) AND @sub_status IN ( @active, @initiated )
  10534.                 BEGIN
  10535.                     /*
  10536.                     ** Set the article status to 'inactive' if there are
  10537.                     ** no other active subscriptions on it.
  10538.                     */
  10539.                     IF NOT EXISTS (SELECT * FROM syssubscriptions WHERE
  10540.                        artid = @artid AND status = @active)
  10541.                     BEGIN
  10542.                         IF EXISTS (SELECT * FROM sysextendedarticlesview WHERE artid = @artid
  10543.                             AND status & 1 = 1)
  10544.                         BEGIN
  10545.                             -- At most one row will be updated in the following two updates as the artid is unique
  10546.                             -- among both sysarticles and sysschemaarticles
  10547.                             UPDATE sysarticles SET status = status & ~1 WHERE
  10548.                                 artid = @artid
  10549.                             IF @@ERROR <> 0
  10550.                             BEGIN
  10551.                                 CLOSE hCsubstatus
  10552.                                 DEALLOCATE hCsubstatus
  10553.                                 if @@trancount > 0
  10554.                                 begin
  10555.                                     ROLLBACK TRANSACTION changesubstatus
  10556.                                     commit tran
  10557.                                 end
  10558.                                 RAISERROR (14069, 16, -1)
  10559.                                 RETURN (1)
  10560.                             END
  10561.                             UPDATE sysschemaarticles SET status = status & ~1 WHERE
  10562.                                 artid = @artid
  10563.                             IF @@ERROR <> 0
  10564.                             BEGIN
  10565.                                 CLOSE hCsubstatus
  10566.                                 DEALLOCATE hCsubstatus
  10567.                                 if @@trancount > 0
  10568.                                 begin
  10569.                                     ROLLBACK TRANSACTION changesubstatus
  10570.                                     commit tran
  10571.                                 end
  10572.                                 RAISERROR (14069, 16, -1)
  10573.                                 RETURN (1)
  10574.                             END
  10575.  
  10576.                             SELECT @art_change = 1
  10577.                         END
  10578.                     END
  10579.  
  10580.                     /*
  10581.                     ** Set the object replication bits  to 'inactive' if
  10582.                     ** there are no other active subscriptions on the
  10583.                     ** table.
  10584.                     */
  10585.                     IF NOT EXISTS (SELECT * FROM syssubscriptions WHERE
  10586.                         artid IN (SELECT sa.artid FROM sysextendedarticlesview sa, syspublications sp WHERE
  10587.                         sa.objid = @tabid and sa.pubid = sp.pubid and sp.repl_freq = 0) AND status = @active)
  10588.                     BEGIN
  10589.                         UPDATE sysobjects SET replinfo =  replinfo & ~@replicate_bit
  10590.                         WHERE id = (SELECT objid FROM sysextendedarticlesview WHERE artid = @artid )
  10591.  
  10592.                         IF @@ERROR <> 0
  10593.                         BEGIN
  10594.                            CLOSE hCsubstatus
  10595.                             DEALLOCATE hCsubstatus
  10596.                             RAISERROR (14068, 16, -1)
  10597.                             if @@trancount > 0
  10598.                             begin
  10599.                                 ROLLBACK TRANSACTION changesubstatus
  10600.                                 commit tran
  10601.                             end
  10602.                             RETURN (1)
  10603.                         END
  10604.                     END
  10605.                 END
  10606.  
  10607.                 -- Note:  Not only do we need to have the replupdateschema already executed
  10608.                 -- so we can handle rollbacks, we also need to
  10609.                 -- acquire the schema lock before RPC to the distributor to avoid livelock
  10610.                 -- with snapshot agents. Snapshot agents acquire lock on user table before
  10611.                 -- updating the distribution db.
  10612.  
  10613.                 if @no_distproc = 0
  10614.                 begin
  10615.                     /*
  10616.                     ** Add the active subscription to the distributor's
  10617.                     ** subscriptions table if changing status from @inactive
  10618.                     */
  10619.                     IF @sub_status = @inactive 
  10620.                     -- From inactive to subscribed or active
  10621.                     BEGIN
  10622.  
  10623.                         DECLARE @null_char sysname
  10624.                         SELECT @null_char = NULL
  10625.  
  10626.                         DECLARE @zero_bit bit
  10627.                         SELECT @zero_bit = 0
  10628.  
  10629.                         SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSadd_subscription'
  10630.                         EXEC @retcode = @distproc @@SERVERNAME, @pub_db, @sub_name, 
  10631.                             @artid, @dest_db, @statusid, @sub_ts,
  10632.                             @publication, 
  10633.                             @null_char, /* Pass null to @article, we already gave @artid */
  10634.                             @subscription_type,
  10635.                             --@immediate_sync, 
  10636.                             @sync_type, 
  10637.                             @zero_bit,
  10638.                             @frequency_type,
  10639.                             @frequency_interval,
  10640.                             @frequency_relative_interval,
  10641.                             @frequency_recurrence_factor,
  10642.                             @frequency_subday,
  10643.                             @frequency_subday_interval,
  10644.                             @active_start_time_of_day,
  10645.                             @active_end_time_of_day,
  10646.                             @active_start_date,
  10647.                             @active_end_date,
  10648.                             @optional_command_line = @optional_command_line,
  10649.                             -- synctran
  10650.                             @update_mode = @update_mode,
  10651.                             @loopback_detection = @loopback_detection,
  10652.                             @distribution_jobid = @distribution_jobid OUTPUT,
  10653.                             @offloadagent = @offloadagent,
  10654.                             @offloadserver = @offloadserver,
  10655.                             @dts_package_name = @dts_package_name,
  10656.                             @dts_package_password = @dts_package_password,
  10657.                             @dts_package_location = @dts_package_location,
  10658.                             @distribution_job_name = @distribution_job_name
  10659.  
  10660.                         IF @@ERROR <> 0 OR @retcode <> 0
  10661.                         BEGIN
  10662.                             CLOSE hCsubstatus
  10663.                             DEALLOCATE hCsubstatus
  10664.                             RAISERROR (14070, 16, -1)
  10665.                             if @@trancount > 0
  10666.                             begin
  10667.                                 ROLLBACK TRANSACTION changesubstatus
  10668.                                 commit tran
  10669.                             end
  10670.                             RETURN (1)
  10671.                         END
  10672.                     END
  10673.                     ELSE
  10674.                     -- From subscribed or active to others
  10675.                     BEGIN
  10676.                         /*
  10677.                         ** Drop the deactivated subscription from the distributor's
  10678.                         ** subscriptions table.
  10679.                         */
  10680.                         IF @statusid = @inactive
  10681.                         -- From subscribed to inactive or from active to inactive
  10682.                         BEGIN
  10683.                             SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSdrop_subscription'
  10684.                             EXEC @retcode = @distproc @@SERVERNAME, @pub_db, @sub_name,  @artid, @dest_db, @publication
  10685.                             IF @@ERROR <> 0 OR @retcode <> 0
  10686.                             BEGIN
  10687.                                 CLOSE hCsubstatus
  10688.                                 DEALLOCATE hCsubstatus
  10689.                                 RAISERROR (14070, 16, -1)
  10690.                                 if @@trancount > 0
  10691.                                 begin
  10692.                                     ROLLBACK TRANSACTION changesubstatus
  10693.                                     commit tran
  10694.                                 end
  10695.                                 RETURN (1)
  10696.                             END
  10697.                         END
  10698.                         ELSE 
  10699.                         -- From subscribed to initiated to active or from active to subscribed.
  10700.                         BEGIN
  10701.                             -- Don't do it if activating the subscription for snapshot agent.
  10702.                             --IF NOT (@from_auto_sync = 1 AND @statusid in(@active, @initiated) )
  10703.                             IF NOT (@from_auto_sync = 1 AND @statusid in(@active) )
  10704.                             BEGIN
  10705.                                 SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSupdate_subscription'
  10706.                                 EXEC @retcode = @distproc @@SERVERNAME, @pub_db, @sub_name, @artid, @statusid, @sub_ts, @dest_db
  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.                         END
  10721.                     END
  10722.                 end
  10723.  
  10724.                 /*
  10725.                 ** Set internal object replication bit  to 'inactive' if
  10726.                 ** there are no other active subscriptions on the
  10727.                 ** table.
  10728.                 */
  10729.  
  10730.                 IF @statusid = @inactive AND @sub_status IN (@active,@initiated) AND
  10731.                     NOT EXISTS (SELECT * FROM syssubscriptions WHERE
  10732.                     artid IN (SELECT artid FROM sysextendedarticlesview WHERE
  10733.                     objid = @tabid) AND status IN (@active,@initiated) )
  10734.                 BEGIN
  10735.                        /*
  10736.                        ** If it's a procedure execution article, clear proc status bits
  10737.                        */
  10738.                        IF (@art_type & 8 ) = 8
  10739.                        BEGIN
  10740.                            UPDATE sysobjects SET replinfo = replinfo & ~24 WHERE id = @tabid
  10741.                        END
  10742.                 END
  10743.  
  10744.  
  10745.                 /* Turn on object replication */
  10746.  
  10747.                 ELSE IF @statusid = @active
  10748.                 BEGIN
  10749.                        IF (@art_type & 24 ) = 24
  10750.                        BEGIN
  10751.  
  10752.                            UPDATE sysobjects SET replinfo = replinfo | 24 WHERE id = @tabid
  10753.                        END
  10754.                        ELSE IF( @art_type & 8 ) = 8
  10755.                        BEGIN
  10756.                            UPDATE sysobjects SET replinfo = replinfo | 8 WHERE id = @tabid
  10757.                        END
  10758.                 END
  10759.  
  10760.  
  10761.                 exec dbo.sp_MSget_qualified_name @tabid, @qualified_name output
  10762.                 exec dbo.sp_replupdateschema @qualified_name, @schemastabilityonly
  10763.  
  10764.                /*
  10765.                ** Get next row.
  10766.                */
  10767.                FETCH hCsubstatus INTO @artid, @tabid, @srvid, @sub_name, @dest_db,
  10768.                @sub_status, @non_sql_flag, @repl_freq, @art_type ,  
  10769.                @immediate_sync, @enabled_for_internet,
  10770.                @allow_anonymous, @subscription_type, @sync_type, @update_mode,
  10771.                 @art_name, @login_name, @loopback_detection, @pubid
  10772.  
  10773.           
  10774.                                     
  10775.            END  -- end while for cursor
  10776.  
  10777.            CLOSE hCsubstatus
  10778.            DEALLOCATE hCsubstatus
  10779.         
  10780.         END -- end while for virtual and real
  10781.  
  10782.         -- force refresh of article cache
  10783.         -- Only do it if necessary
  10784.         -- No need on brute force cleanup
  10785.         IF ( @art_change = 1 ) and ( @ignore_distributor = 0 )
  10786.             EXECUTE dbo.sp_replflush
  10787.  
  10788.     COMMIT TRANSACTION
  10789.     drop table #sysextendedarticlesview
  10790.     RETURN(0)
  10791. go
  10792.  
  10793. EXEC dbo.sp_MS_marksystemobject sp_changesubstatus
  10794. GO
  10795.  
  10796. print ''
  10797. print 'Creating procedure sp_addsubscription'
  10798. go
  10799. CREATE PROCEDURE sp_addsubscription (
  10800.     @publication sysname,                            /* publication name */
  10801.     @article sysname = 'all',                        /* article name */
  10802.     @subscriber sysname = NULL,                        /* subscriber name */
  10803.     @destination_db sysname = NULL,                /* destination database */
  10804.     @sync_type nvarchar (15) = 'automatic',                /* subscription sync type */
  10805.     @status sysname = NULL,                            /* subscription status */
  10806.     @subscription_type nvarchar(4) = 'push',                /* subscription type:
  10807.                                                         ** 'push' or 'pull' */
  10808.     -- SyncTran
  10809.     @update_mode           nvarchar(30)    = 'read only',    -- Can be 'read only', 'sync tran', 'queued tran', 'failover'
  10810.     @loopback_detection nvarchar(5) = NULL, -- 'true' or 'false'
  10811.     -- end SyncTran
  10812.  
  10813.     @frequency_type int = NULL,
  10814.     @frequency_interval int = NULL,
  10815.     @frequency_relative_interval int = NULL,
  10816.     @frequency_recurrence_factor int = NULL,
  10817.     @frequency_subday int = NULL,
  10818.     @frequency_subday_interval int = NULL,
  10819.     @active_start_time_of_day int = NULL,
  10820.     @active_end_time_of_day int = NULL,
  10821.     @active_start_date int = NULL,
  10822.     @active_end_date int = NULL,
  10823.     @optional_command_line nvarchar(4000) = NULL,
  10824.     
  10825.     @reserved nvarchar(10) = NULL,          /* reserved, used when calling from other system */
  10826.                                             /* stored procedures, it will be set to 'internal'.*/
  10827.                                             /* It should never be used directly */
  10828.     @enabled_for_syncmgr nvarchar(5) = 'false', /* Enabled for SYNCMGR: true or false */
  10829.     -- Agent offload
  10830.     @offloadagent bit = 0,
  10831.     @offloadserver sysname = NULL,
  10832.     -- End of agent offload
  10833.     -- DTS package name
  10834.     @dts_package_name sysname  = NULL,    /* value will be sent and validated at distributor */                                  
  10835.      @dts_package_password  sysname = NULL,
  10836.     @dts_package_location nvarchar(12) = N'distributor',
  10837.     @distribution_job_name sysname = NULL
  10838.    ) AS
  10839.  
  10840.     SET NOCOUNT ON
  10841.  
  10842.     /*
  10843.     ** Declarations.
  10844.     */
  10845.  
  10846.     DECLARE @artid int
  10847.     DECLARE @pre_creation_cmd tinyint
  10848.     DECLARE @none tinyint
  10849.     DECLARE @automatic tinyint
  10850.     DECLARE @cmd nvarchar(255)
  10851.     DECLARE @cmd2 nvarchar(255)
  10852.     DECLARE @inactive tinyint
  10853.     DECLARE @active tinyint
  10854.     DECLARE @subscribed tinyint
  10855.     DECLARE @manual tinyint
  10856.     DECLARE @pubid int
  10857.     DECLARE @retcode int
  10858.     DECLARE @srvid smallint
  10859.     DECLARE @subscriber_bit smallint
  10860.     DECLARE @sync_typeid tinyint
  10861.     DECLARE @non_sql_flag bit
  10862.     DECLARE @truncate tinyint
  10863.     DECLARE @sync_method tinyint
  10864.     DECLARE @char_bcp tinyint
  10865.     DECLARE @concurrent tinyint
  10866.     DECLARE @concurrent_char tinyint
  10867.     DECLARE @internal nvarchar(10)
  10868.     DECLARE @status_id tinyint
  10869.     DECLARE @virtual_id smallint
  10870.     DECLARE @subscription_type_id int /* 0 push, 1 pull */
  10871.     DECLARE @immediate_sync bit    /* publication type */
  10872.     DECLARE @count_subs int
  10873.     DECLARE @count_arts int
  10874.     DECLARE @distribution_jobid binary(16)
  10875.     DECLARE @pubstatus tinyint
  10876.     DECLARE @allow_anonymous bit
  10877.     DECLARE @immediate_sync_ready bit
  10878.     declare @loopback_detection_id bit
  10879.     declare @independent_agent_id bit
  10880.     DECLARE @platform_nt binary
  10881.             ,@artsrctabid int
  10882.  
  10883.     DECLARE @dsn_dbname sysname
  10884.     DECLARE @dts_package_enc_password nvarchar(524)
  10885.  
  10886.     -- SyncTran
  10887.     DECLARE @allow_sync_tran_id bit
  10888.     DECLARE @allow_queued_tran_id bit
  10889.     DECLARE @update_mode_id     tinyint -- 0 = read only, 1 = sync tran, 2 = queued tran, 3 = failover
  10890.                                         -- 4 = sqlqueued tran, 5 = sqlqueued failover
  10891.     DECLARE    @publication_queue_type int 
  10892.     -- end SyncTran
  10893.  
  10894.     /*
  10895.     ** Initializations.
  10896.     */
  10897.  
  10898.     SELECT @none = 2            /* Const: synchronization type 'none' */
  10899.     SELECT @automatic = 1       /* Const: synchronization type 'automatic' */
  10900.     SELECT @manual = 0          /* Const: synchronization type 'manual' */
  10901.     SELECT @inactive = 0        /* Const: subscription status 'inactive' */
  10902.     SELECT @subscribed = 1        /* Const: subscription status 'subscribed' */
  10903.     SELECT @active = 2        /* Const: subscription status 'arctive' */
  10904.     SELECT @subscriber_bit = 4  /* Const: subscription server status */
  10905.     SELECT @truncate = 3    /* Const: truncate pre-creation command */
  10906.     SELECT @char_bcp = 1    /* Const: character bcp sync method */
  10907.     SELECT @concurrent = 3  /* Const: concurrent sync method */
  10908.     SELECT @concurrent_char = 4  /* Const: concurrent char mode sync method */
  10909.     SELECT @virtual_id = -1 /* Const: virtual subscriber id */
  10910.     SELECT @internal = 'internal' /* Const: Flag of calling internally from system */
  10911.                                   /* stored procedures     */
  10912.     
  10913.     -- Change it  in 7.5 to avoid confusion, expecially in ole db case
  10914.     -- SELECT @dsn_dbname = 'DSN'
  10915.     SELECT @dsn_dbname = formatmessage(20586)
  10916.     SELECT @platform_nt = 0x1
  10917.  
  10918.     /*
  10919.     ** Parameter Check: @publication.
  10920.     ** Check to make sure that the publication exists and that it conforms
  10921.     ** to the rules for identifiers.
  10922.     ** set subscription_type for the publication
  10923.     */
  10924.  
  10925.     IF @publication IS NOT NULL
  10926.         BEGIN
  10927.             
  10928.             EXECUTE @retcode = dbo.sp_validname @publication
  10929.  
  10930.             IF @retcode <> 0
  10931.         RETURN (1)
  10932.  
  10933.             IF NOT EXISTS (SELECT * FROM syspublications WHERE name = @publication)
  10934.                 BEGIN
  10935.                     RAISERROR (20026, 11, -1, @publication)
  10936.                     RETURN (1)
  10937.                 END
  10938.  
  10939.         END
  10940.  
  10941.     /*
  10942.     ** Parameter Check: @subscription_type
  10943.     ** Valid values:
  10944.     ** push
  10945.     ** pull
  10946.     **
  10947.     */
  10948.  
  10949.     IF LOWER(@subscription_type) NOT IN ('push', 'pull')
  10950.         BEGIN
  10951.             RAISERROR (14128, 16, -1)    
  10952.             RETURN (1)
  10953.         END
  10954.  
  10955.     IF LOWER(@subscription_type) = 'push'
  10956.         SELECT @subscription_type_id = 0
  10957.     ELSE 
  10958.         SELECT @subscription_type_id = 1
  10959.  
  10960.     /*
  10961.     ** Parameter Check: @offloadagent
  10962.     ** Valid values: 0 or 1 
  10963.     ** If @offloadagent = 1 then @subscription_type must be 'push'
  10964.     */
  10965.     IF (@offloadagent = 1 AND LOWER(@subscription_type) <> 'push')
  10966.     BEGIN
  10967.         RAISERROR(21138, 16, -1)
  10968.         RETURN (1)
  10969.     END 
  10970.  
  10971.  
  10972.     /*
  10973.     ** Parameter Check: @offloadserver
  10974.     ** Make sure that @offlaod server doesn't contain any invalid characters
  10975.     */
  10976.     EXEC @retcode = sp_MSreplcheckoffloadserver @offloadserver
  10977.     IF @retcode<>0 OR @@error<>0
  10978.         RETURN (1)
  10979.     /*
  10980.     ** Security Check.
  10981.     */
  10982.  
  10983.     IF @subscription_type_id = 0 
  10984.     BEGIN
  10985.         exec @retcode = dbo.sp_MSreplcheck_publish
  10986.         if @@ERROR <> 0 or @retcode <> 0
  10987.             return(1)
  10988.     END
  10989.     ELSE
  10990.     BEGIN
  10991.         exec @retcode = dbo.sp_MSreplcheck_pull @publication
  10992.         if @@ERROR <> 0 or @retcode <> 0
  10993.             return(1)
  10994.     END
  10995.  
  10996.    declare @allow_dts bit
  10997.  
  10998.    SELECT @pubid = pubid, @sync_method = sync_method, 
  10999.         @immediate_sync = immediate_sync, @pubstatus = status, 
  11000.         @allow_anonymous = allow_anonymous, 
  11001.         @immediate_sync_ready = immediate_sync_ready,
  11002.         -- SyncTran
  11003.         @allow_sync_tran_id = allow_sync_tran,
  11004.         @allow_queued_tran_id = allow_queued_tran,
  11005.         @independent_agent_id = independent_agent,
  11006.         @allow_dts = allow_dts
  11007.         ,@publication_queue_type = queue_type
  11008.     FROM syspublications WHERE name = @publication
  11009.  
  11010.     select @srvid = srvid from master..sysservers where UPPER(srvname)=UPPER(@subscriber) collate database_default
  11011.  
  11012.     if exists (select name from sysobjects where name='sysmergesubscriptions')
  11013.         begin
  11014.             IF exists (select name from sysextendedarticlesview where pubid=@pubid and 
  11015.                 objid in (select objid from sysmergeextendedarticlesview where 
  11016.                     pubid in (select pubid from sysmergesubscriptions where db_name=@destination_db and srvid=@srvid)))
  11017.             begin
  11018.                 RAISERROR(21281, 16, -1, @publication, @destination_db)
  11019.                 return (1)
  11020.             end
  11021.         end
  11022.  
  11023.  
  11024.     IF @pubid IS NULL
  11025.         BEGIN
  11026.             RAISERROR (14043, 16, -1, '@pubid')
  11027.             RETURN (1)
  11028.         END
  11029.  
  11030.     /* 
  11031.     ** If publication is of concurrent sync, then all articles must
  11032.     ** be subscribed to
  11033.     */
  11034.     IF @sync_method IN( @concurrent, @concurrent_char) AND
  11035.        LOWER(@article) != 'all' AND
  11036.        @reserved != @internal
  11037.     BEGIN
  11038.         RAISERROR( 14100, 16, -1 )
  11039.         RETURN (1)
  11040.     END
  11041.  
  11042.     /* 
  11043.     ** Check to see if the desired subscription type is allowed
  11044.     */
  11045.     /* 
  11046.     ** push 
  11047.     ** Virtual subscriptions are always push type
  11048.     */
  11049.     IF @subscription_type_id = 0 AND @subscriber IS NOT NULL
  11050.     BEGIN
  11051.         IF NOT EXISTS (SELECT * from syspublications where
  11052.             allow_push = 1 AND
  11053.             pubid = @pubid)
  11054.         BEGIN
  11055.             RAISERROR (20012, 16, -1, @subscription_type, @publication)    
  11056.             RETURN (1)
  11057.         END
  11058.     END
  11059.         
  11060.     /* pull */
  11061.     IF @subscription_type_id = 1 AND @subscriber IS NOT NULL
  11062.     BEGIN
  11063.         IF NOT EXISTS (SELECT * from syspublications where
  11064.             allow_pull = 1 AND
  11065.             pubid = @pubid)
  11066.         BEGIN
  11067.             RAISERROR (20012, 16, -1, @subscription_type, @publication)    
  11068.             RETURN (1)
  11069.         END
  11070.     END
  11071.  
  11072.  /*
  11073.     ** Parameter Check: @subscriber.
  11074.     **
  11075.     ** Check if the server exists and that it is a subscription server.
  11076.     **
  11077.     ** @subscriber is NULL represent virtual subscription, which is not allowed
  11078.     ** in following case:
  11079.     ** 1. Non-immediate-sync publication
  11080.     ** 2. the stored procedure is not in the internal usage mode 
  11081.     **        (called by system stored procedures)
  11082.     ** 3. non push mode
  11083.     ** 
  11084.     */
  11085.  
  11086.     IF  @subscriber IS NULL AND (
  11087.         @immediate_sync = 0 OR
  11088.         @subscription_type_id <> 0 OR
  11089.         @reserved <> @internal)
  11090.         BEGIN
  11091.             RAISERROR (14043, 16, -1, '@subscriber')
  11092.             RETURN (1)
  11093.         END
  11094.  
  11095.  
  11096.     IF @subscriber IS NULL
  11097.         BEGIN
  11098.         /* set virtual subscriber ID */
  11099.             SELECT @srvid = @virtual_id 
  11100.             select @non_sql_flag = 0
  11101.         END
  11102.     ELSE
  11103.         BEGIN
  11104.             /* validate name and get subscriber ID  and server status  */
  11105.             EXECUTE @retcode = dbo.sp_validname @subscriber
  11106.  
  11107.             IF @retcode <> 0
  11108.             RETURN (1)
  11109.  
  11110.             select @srvid = null
  11111.             SELECT @srvid = srvid, @non_sql_flag = 
  11112.                 case when srvproduct = N'MSREPL-NONSQL' then 1
  11113.                 else 0 end
  11114.               FROM master..sysservers
  11115.              WHERE UPPER(srvname) = UPPER(@subscriber) collate database_default
  11116.                AND (srvstatus & @subscriber_bit) <> 0
  11117.  
  11118.             IF @srvid IS NULL
  11119.                 BEGIN
  11120.                     RAISERROR (14010, 16, -1)
  11121.                    RETURN (1)
  11122.                 END
  11123.         END
  11124.  
  11125.     /*
  11126.     ** Parameter Check: @destination_db.
  11127.     ** @destination_db can not be all. 
  11128.     ** Set @destination_db to current database if not specified.  Make
  11129.     ** sure that the @destination_db conforms to the rules for identifiers.
  11130.     */
  11131.  
  11132.     if LOWER(@destination_db) = 'all'
  11133.     BEGIN
  11134.         RAISERROR (14032, 16, -1, '@destination_db')
  11135.         RETURN (1)
  11136.     END
  11137.  
  11138.     IF @destination_db IS not NULL
  11139.     begin
  11140.         EXECUTE @retcode = dbo.sp_validname @destination_db
  11141.         IF @retcode <> 0
  11142.         RETURN (1)
  11143.     end
  11144.  
  11145.     /*
  11146.     ** Parameter Check:  @article
  11147.     */
  11148.  
  11149.     /* @article can not be null     */
  11150.     IF @article IS NULL
  11151.         BEGIN
  11152.             RAISERROR (14043, 16, -1, '@article')
  11153.             RETURN (1)
  11154.         END
  11155.  
  11156.     -- Queued Tran
  11157.     -- SyncTran
  11158.     /*
  11159.     ** Parameter check: @update_mode
  11160.     */
  11161.     IF @update_mode IS NULL OR LOWER(@update_mode) NOT IN ('read only', 'sync tran', 'queued tran', 'failover')
  11162.     BEGIN
  11163.         RAISERROR (20502, 16, -1, '@update_mode')
  11164.         RETURN (1)
  11165.     END
  11166.  
  11167.     IF (LOWER(@update_mode) = 'sync tran') 
  11168.     BEGIN
  11169.         SELECT @update_mode_id = 1
  11170.        
  11171.         -- Check if publication allows this option
  11172.         IF @allow_sync_tran_id <> 1
  11173.         BEGIN
  11174.             RAISERROR (20503, 16, -1, '@update_mode', 'sp_addsubscription','sync tran')
  11175.             RETURN (1)
  11176.         END
  11177.     END
  11178.     ELSE IF (LOWER(@update_mode) = 'queued tran')
  11179.     BEGIN        
  11180.         SELECT @update_mode_id = case 
  11181.             when (@publication_queue_type = 2) then 4
  11182.             else 2 end
  11183.        
  11184.         -- Check if publication allows this option
  11185.         -- If the publication allow synctran, it allows queued tran.
  11186.         IF @allow_queued_tran_id <> 1
  11187.         BEGIN
  11188.             RAISERROR (20503, 16, -1, '@update_mode', 'sp_addsubscription', 'queued tran')
  11189.             RETURN (1)
  11190.         END
  11191.     END
  11192.     ELSE IF (LOWER(@update_mode) = 'failover')
  11193.     BEGIN
  11194.         SELECT @update_mode_id = case
  11195.             when (@publication_queue_type = 2) then 5
  11196.             else 3 end
  11197.        
  11198.         -- Check if publication allows this option
  11199.         IF @allow_sync_tran_id <> 1
  11200.         BEGIN
  11201.             RAISERROR (20503, 16, -1, '@update_mode', 'sp_addsubscription', 'sync tran')
  11202.             RETURN (1)
  11203.         END
  11204.  
  11205.         -- Check if publication allows this option
  11206.         IF @allow_queued_tran_id <> 1
  11207.         BEGIN
  11208.             RAISERROR (20503, 16, -1, '@update_mode', 'sp_addsubscription','queued tran')
  11209.             RETURN (1)
  11210.         END
  11211.     END
  11212.     ELSE 
  11213.     BEGIN
  11214.         SELECT @update_mode_id = 0
  11215.     END
  11216.     -- end SyncTran
  11217.     -- end Queued Tran
  11218.  
  11219.     /*
  11220.     ** Parameter Check: @dts_package_location
  11221.     ** Valid values:
  11222.     ** distributor
  11223.     ** subscriber
  11224.     **
  11225.     */
  11226.     IF LOWER(@dts_package_location) NOT IN ('distributor', 'subscriber')
  11227.     BEGIN
  11228.         RAISERROR(21179, 16, -1)    
  11229.         RETURN (1)
  11230.     END
  11231.  
  11232.     declare @dts_package_location_id int
  11233.  
  11234.     IF LOWER(@dts_package_location) = 'distributor'
  11235.         SELECT @dts_package_location_id = 0
  11236.     ELSE 
  11237.         SELECT @dts_package_location_id = 1
  11238.  
  11239.     -- Have to be a push, non updatable  subscription to set DTS package name
  11240.     if @dts_package_name is not null
  11241.     begin
  11242.         if    @subscription_type_id != 0
  11243.         begin
  11244.             RAISERROR(21181, 16, -1)    
  11245.             RETURN (1)
  11246.         end
  11247.         if    @allow_dts = 0
  11248.         begin
  11249.             RAISERROR(21178, 16, -1)    
  11250.             RETURN (1)
  11251.         end
  11252.     end
  11253.     
  11254.     /** For immediate_sync publication, @article has to be 'all'     */
  11255.     IF NOT @reserved = @internal AND @immediate_sync = 1
  11256.         AND NOT LOWER(@article) = 'all'
  11257.         BEGIN
  11258.             RAISERROR (14122, 16, -1)
  11259.             RETURN (1)
  11260.         END
  11261.  
  11262.     /* 
  11263.     ** For full subscription, check to see if  subscriptions
  11264.     ** to ALL the articles exist before expanding parameter @article.
  11265.     **
  11266.     */
  11267.     IF LOWER(@article) = 'all' AND @reserved <> @internal AND
  11268.         EXISTS (SELECT * FROM syspublications WHERE pubid = @pubid)
  11269.     BEGIN
  11270.         SELECT @count_arts = count(*) FROM sysextendedarticlesview art
  11271.             WHERE art.pubid = @pubid 
  11272.  
  11273.         if @count_arts = 0
  11274.         BEGIN
  11275.             RAISERROR (14124, 16, -1)
  11276.             RETURN(1)
  11277.         END
  11278.  
  11279.         SELECT @count_subs = count(*) FROM syssubscriptions sub, 
  11280.                   sysextendedarticlesview art
  11281.             WHERE sub.srvid = @srvid
  11282.               AND sub.srvid >= 0
  11283.               AND sub.dest_db = @destination_db --or @non_sql_flag <> 0)
  11284.               AND sub.artid = art.artid
  11285.               AND art.pubid = @pubid
  11286.  
  11287.         IF @count_arts = @count_subs
  11288.         BEGIN
  11289.               RAISERROR (14058, 16, -1)
  11290.               RETURN (1)
  11291.         END
  11292.     END
  11293.  
  11294.     /* 
  11295.     ** Real subscription to inactive publicaton is not allowed
  11296.     ** Note, subscriptions to the new article will be added automatically
  11297.     ** for immediate_sync publications. At that time, the publication may not
  11298.     ** be active.
  11299.     */
  11300.  
  11301.     IF  @srvid <> @virtual_id AND @pubstatus = 0 AND @reserved <> @internal
  11302.         BEGIN
  11303.             RAISERROR (21000, 16, -1)
  11304.             RETURN (1)
  11305.         END
  11306.  
  11307.  
  11308.     -- If the publication is 'allow_dts', push subscription has to specify a DTS package.
  11309.     -- Error check that disallow ODBC subscriber to subscriber with DTS package
  11310.     -- is at the distributor.
  11311.     -- Show dts error first, otherwise user will get 21060 below which is confusing
  11312.     IF @allow_dts <> 0 and @dts_package_name is null and @subscriber IS not NULL and
  11313.         @reserved is null and @subscription_type_id = 0
  11314.     begin
  11315.         raiserror(21213, 16, -1)
  11316.         return(1)
  11317.     end
  11318.  
  11319.     /* 
  11320.     ** Do special things for DSN subscribers.
  11321.     */
  11322.     IF @subscriber IS NOT NULL AND @non_sql_flag <> 0
  11323.     BEGIN
  11324.         -- DSN or oledb subscriber not using DTS 
  11325.         -- cannot subscribe to native mode or concurrent snapshot publication
  11326.         IF @sync_method <> @char_bcp and @dts_package_name is null
  11327.         BEGIN
  11328.             RAISERROR (14095, 16, -1, @publication, @subscriber)
  11329.             RETURN (1)
  11330.         END
  11331.  
  11332.         -- DSN subscriber cannot subscribe with 'Sync Update'
  11333.         IF @update_mode_id <> 0
  11334.         BEGIN
  11335.             RAISERROR (21032, 16, -1, @subscriber)
  11336.             RETURN (1)
  11337.         END
  11338.  
  11339.         -- DSN subscriber cannot subscribe to article using custom procs
  11340.         -- or articles using parameterized statements
  11341.         -- ( only run this test during execs when the article name is actually specified )
  11342.         IF( LOWER( @article ) <> 'all' )
  11343.         BEGIN
  11344.             --IF EXISTS ( select * from sysextendedarticlesview sa, syspublications sp
  11345.                         --where sa.pubid = sp.pubid 
  11346.                         --and sp.name = @publication
  11347.                         --and sa.name = @article
  11348.                         --and ( ins_cmd like '%call%' or upd_cmd like '%call%' or del_cmd like '%call%' ) )
  11349.             --BEGIN
  11350.                 --RAISERROR(21051, 16, -1, @subscriber)
  11351.                 --RETURN (1)
  11352.             --END
  11353.             
  11354.             declare @art_status tinyint
  11355.  
  11356.             select @art_status = sa.status, @artsrctabid = sa.objid 
  11357.             from sysarticles sa, syspublications sp
  11358.                 where sa.pubid = sp.pubid 
  11359.                 and sp.name = @publication
  11360.                 and sa.name = @article
  11361.  
  11362.             -- OLEDB or ODBC subscriber can not subscribe to article with parameterized command 
  11363.             -- unless using DTS 
  11364.             IF @dts_package_name is null and @art_status & 16 = 16 
  11365.             BEGIN
  11366.                 RAISERROR(21060, 16, -1, @subscriber)
  11367.                 RETURN (1)
  11368.             END
  11369.  
  11370.             -- OLEDB or ODBC subscribers can not subscriber to article with subscriber managed
  11371.             -- timestamp column
  11372.             if @art_status & 32 = 32
  11373.             begin
  11374.                 raiserror(21249, 16, -1, @article, @publication)
  11375.                 return (1)
  11376.             end
  11377.  
  11378.         END
  11379.     END
  11380.  
  11381.     -- DNS may define db.  If no db given, specify that DSN default should be used.
  11382.     -- use internal values
  11383.     if @subscriber IS NOT NULL and @destination_db is NULL
  11384.     begin
  11385.         IF @non_sql_flag <> 0 
  11386.             SELECT @destination_db = @dsn_dbname
  11387.         else
  11388.             SELECT @destination_db = DB_NAME()
  11389.     end
  11390.  
  11391.     -- if we're subscribing to a dump type publication, error
  11392.     -- out if this subscriber has any other subscriptions to publications
  11393.     -- other than this one
  11394.  
  11395.     IF @sync_method = 2
  11396.     BEGIN
  11397.         IF EXISTS( SELECT * FROM syssubscriptions sub, sysextendedarticlesview art
  11398.                 WHERE sub.srvid = @srvid
  11399.                   AND sub.srvid >= 0
  11400.                   AND sub.dest_db = @destination_db
  11401.                   AND sub.artid = art.artid
  11402.                   AND art.pubid != @pubid )
  11403.         BEGIN
  11404.             RAISERROR(21144, 16, -1)
  11405.             RETURN 1
  11406.         END
  11407.     END
  11408.  
  11409.     -- else if we're subscribing to a char or native mode publication, 
  11410.     -- error out if the subscriber is subscribed to any dump type publications
  11411.     ELSE
  11412.     BEGIN
  11413.         IF EXISTS( SELECT * FROM syssubscriptions sub, sysextendedarticlesview art, syspublications pub
  11414.                 WHERE sub.srvid = @srvid
  11415.                   AND sub.srvid >= 0
  11416.                   AND sub.dest_db = @destination_db
  11417.                   AND sub.artid = art.artid
  11418.                   AND art.pubid != @pubid
  11419.                   AND pub.pubid = art.pubid
  11420.                   AND pub.sync_method = 2 )
  11421.  
  11422.         BEGIN
  11423.             RAISERROR(21145, 16, -1, @publication )
  11424.             RETURN 1
  11425.         END
  11426.     END
  11427.  
  11428.  
  11429.     IF LOWER(@article) = 'all' 
  11430.     /*
  11431.     ** Get all articles in the publication that are not subscribed to
  11432.     ** by the @subscriber
  11433.     */
  11434.     BEGIN
  11435.             /*
  11436.             ** Make the operation atomic. This is to prevent multiple subscription_type
  11437.             ** from one subscriber on an immediate_sync publication
  11438.             */
  11439.             BEGIN TRAN 
  11440.  
  11441.             DECLARE hCx CURSOR LOCAL FAST_FORWARD FOR  SELECT DISTINCT a.name
  11442.                 FROM sysextendedarticlesview a, syspublications b  
  11443.                 WHERE a.pubid = b.pubid 
  11444.                 AND b.name = @publication
  11445.                 AND NOT EXISTS (SELECT * from syssubscriptions s 
  11446.                     WHERE s.artid = a.artid AND s.status <> 0 AND s.srvid = @srvid
  11447.                     AND s.dest_db = @destination_db)
  11448.             FOR READ ONLY
  11449.  
  11450.             EXECUTE (@cmd + @cmd2)
  11451.             OPEN hCx
  11452.             FETCH hCx INTO @article
  11453.  
  11454.             WHILE (@@fetch_status <> -1)
  11455.                 BEGIN
  11456.                     EXECUTE @retcode = dbo.sp_addsubscription 
  11457.                                 @publication       = @publication,
  11458.                                 @article        = @article,
  11459.                                 @subscriber     = @subscriber,
  11460.                                 @destination_db = @destination_db,
  11461.                                 @sync_type      = @sync_type,
  11462.                                 @status            = @status,
  11463.                                 @subscription_type = @subscription_type,
  11464.                                 @reserved       = @internal,
  11465.                                 -- SyncTran
  11466.                                 @update_mode    = @update_mode,      
  11467.                                 -- end SyncTran
  11468.                                 @loopback_detection = @loopback_detection,
  11469.                                 @frequency_type  = @frequency_type,
  11470.                                 @frequency_interval  = @frequency_interval,
  11471.                                 @frequency_relative_interval  = @frequency_relative_interval,
  11472.                                 @frequency_recurrence_factor  = @frequency_recurrence_factor,
  11473.                                 @frequency_subday  = @frequency_subday,
  11474.                                 @frequency_subday_interval  = @frequency_subday_interval,
  11475.                                 @active_start_time_of_day  = @active_start_time_of_day,
  11476.                                 @active_end_time_of_day  = @active_end_time_of_day,
  11477.                                 @active_start_date  = @active_start_date,
  11478.                                 @active_end_date  = @active_end_date,
  11479.                                 @optional_command_line = @optional_command_line,
  11480.                                 @offloadserver = @offloadserver,
  11481.                                 @offloadagent = @offloadagent,
  11482.                                 @dts_package_name = @dts_package_name,
  11483.                                 @dts_package_password = @dts_package_password,
  11484.                                 @dts_package_location = @dts_package_location,
  11485.                                 @distribution_job_name = @distribution_job_name
  11486.     
  11487.  
  11488.                     IF @@error <> 0 OR @retcode <> 0
  11489.                     BEGIN
  11490.                        CLOSE hCx
  11491.                        DEALLOCATE hCx
  11492.                        if @@trancount > 0
  11493.                             ROLLBACK TRAN 
  11494.                        RETURN (1)
  11495.                     END
  11496.                     FETCH hCx INTO @article
  11497.                 END
  11498.             CLOSE hCx
  11499.             DEALLOCATE hCx
  11500.  
  11501.             COMMIT TRAN
  11502.  
  11503.             RETURN (0)
  11504.         END
  11505.  
  11506.    
  11507.     /* After 'all' being expanded, check to make sure that the article exists, 
  11508.     ** is not NULL, and conforms to the rules for identifiers.
  11509.     */
  11510.     /*
  11511.     EXECUTE @retcode = dbo.sp_validname @article
  11512.     IF @retcode <> 0
  11513.     RETURN (1)
  11514.     */
  11515.  
  11516.     declare @dest_owner sysname
  11517.  
  11518.     SELECT @artid = artid, @pre_creation_cmd = pre_creation_cmd,
  11519.         @dest_owner = dest_owner
  11520.     FROM sysextendedarticlesview
  11521.     WHERE name = @article
  11522.     AND pubid = @pubid
  11523.  
  11524.     IF NOT EXISTS (SELECT *
  11525.                              FROM sysextendedarticlesview
  11526.                             WHERE artid = @artid
  11527.                               AND pubid = @pubid)
  11528.         BEGIN
  11529.             RAISERROR (20027, 11, -1, @article)
  11530.             RETURN (1)
  11531.         END
  11532.  
  11533.  
  11534.     /*
  11535.     ** If the subscriber is an ODBC DSN, do not allow subscriptions to
  11536.     ** articles with a "truncate" pre_creation_cmd.
  11537.     */
  11538.     IF @non_sql_flag <> 0 AND @pre_creation_cmd = @truncate
  11539.         BEGIN
  11540.             RAISERROR (14094, 16, -1, @article, @subscriber)
  11541.             RETURN (1)
  11542.         END
  11543.  
  11544.     IF @non_sql_flag <> 0 AND @dest_owner is not null and @dest_owner <> N''
  11545.         BEGIN
  11546.             --RAISERROR (21039, 16, -1, @article, @subscriber)
  11547.             -- YWU: UNDONE fix the message after Beta2
  11548.             RAISERROR (21039, 16, -1)
  11549.             RETURN (1)
  11550.         END
  11551.  
  11552.    /*
  11553.    ** Parameter Check: @sync_type.
  11554.    ** Set sync_typeid based on the @sync_type specified.
  11555.    **
  11556.    **   sync_typeid     sync_type
  11557.    **   ===========     =========
  11558.    **             0     manual
  11559.    **             1     automatic
  11560.    **             2     none
  11561.    */
  11562.  
  11563.  
  11564.    IF LOWER(@sync_type) NOT IN ('automatic', 'manual', 'none')
  11565.        BEGIN
  11566.            RAISERROR (14052, 16, -1)
  11567.            RETURN (1)
  11568.        END
  11569.  
  11570.    IF LOWER(@sync_type) = 'manual'
  11571.        BEGIN
  11572.            RAISERROR (14123, 16, -1)
  11573.            RETURN (1)
  11574.        END
  11575.  
  11576.  
  11577.    IF LOWER(@sync_type) = 'automatic'
  11578.    BEGIN
  11579.         SELECT @sync_typeid = @automatic
  11580.    END
  11581.    ELSE
  11582.    BEGIN
  11583.         SELECT @sync_typeid = @none
  11584.    END
  11585.  
  11586.  
  11587.     /*
  11588.     ** Parameter Check: @status
  11589.     ** If the publication is immediate_sync type and sync_type is automatic
  11590.     ** the status has to be NULL.
  11591.     ** Note for 6x backward compatibility, don't do the check for non immediate_sync
  11592.     ** publication
  11593.     */
  11594.     IF @immediate_sync = 1 and @sync_typeid = @automatic AND 
  11595.         @status IS NOT NULL
  11596.     BEGIN
  11597.           RAISERROR (14129, 16, -1)
  11598.           RETURN (1)
  11599.     END
  11600.  
  11601.     /*
  11602.     ** Parameter Check:  @loopback_detection
  11603.     */
  11604.     IF @loopback_detection is not null and LOWER(@loopback_detection) 
  11605.         NOT IN ('true', 'false')
  11606.     BEGIN
  11607.         RAISERROR (14148, 16, -1, '@loopback_detection')
  11608.         RETURN (1)
  11609.     END
  11610.  
  11611.     IF  LOWER(@loopback_detection) = 'true'  
  11612.         SELECT @loopback_detection_id = 1
  11613.     ELSE IF LOWER(@loopback_detection) = 'false' 
  11614.         SELECT @loopback_detection_id = 0
  11615.     ELSE 
  11616.     -- if @loopback_detection is null, we will chose the value
  11617.     begin
  11618.         -- turn on loopback detection for sync and queued
  11619.         if @update_mode_id in (1,2,3,4,5) 
  11620.             select @loopback_detection_id = 1
  11621.         else
  11622.             select @loopback_detection_id = 0
  11623.     end
  11624.  
  11625.     select @dts_package_enc_password = @dts_package_password
  11626.     if @dts_package_password is not null
  11627.     begin
  11628.         EXEC @retcode = master.dbo.xp_repl_encrypt @dts_package_enc_password OUTPUT
  11629.         IF @@error <> 0 OR @retcode <> 0
  11630.             return 1
  11631.     end
  11632.  
  11633.     --
  11634.     -- For updating subscriptions (immediate)
  11635.     -- Check if there exists an subscription to the same
  11636.     -- dest_db which contain at least one article which has 
  11637.     -- the same source_table as the current article - 
  11638.     -- If yes then raise a warning
  11639.     -- NOTE : this restriction is due to the fact that loopback
  11640.     -- detection happens at database level and hence for updating
  11641.     -- subscriptions, we can lose the updates made in one subscription
  11642.     -- w.r.t. the other subscription
  11643.     --
  11644.     if (@update_mode_id = 1)
  11645.     begin
  11646.         if exists (select * from dbo.syssubscriptions 
  11647.             where srvid = @srvid and dest_db = @destination_db and artid in 
  11648.                 (select artid from dbo.sysarticles 
  11649.                     where objid = (select objid from sysarticles where artid = @artid)))
  11650.         begin
  11651.             raiserror(21293, 10, 1, @article, @destination_db)
  11652.         end
  11653.     end
  11654.  
  11655.     /*
  11656.     ** Add subscription to syssubscriptions
  11657.     */
  11658.     begin tran
  11659.     save TRAN addsubscription
  11660.  
  11661.     /*
  11662.     ** If no subscription exists, add it to syssubscriptions.
  11663.     */
  11664.     IF NOT EXISTS (SELECT *
  11665.                      FROM syssubscriptions
  11666.                     WHERE srvid = @srvid
  11667.                       AND artid = @artid
  11668.                       AND dest_db = @destination_db )--or @non_sql_flag <> 0))
  11669.         BEGIN
  11670.        INSERT syssubscriptions (artid,
  11671.                                     srvid,
  11672.                                     dest_db,
  11673.                                     login_name,
  11674.                                     status,
  11675.                                     sync_type,
  11676.                                     subscription_type,
  11677.                                     distribution_jobid,
  11678.                                     -- SyncTran
  11679.                                     update_mode,
  11680.                                     loopback_detection,
  11681.                                     queued_reinit)
  11682.                                  /*  timestamp) */
  11683.        VALUES (@artid,
  11684.                    @srvid,
  11685.                    @destination_db,    
  11686.                    suser_sname(suser_sid()),
  11687.                    @inactive,
  11688.                    @sync_typeid,
  11689.                    @subscription_type_id,
  11690.                    0,
  11691.                    -- SyncTran
  11692.                    @update_mode_id,
  11693.                    @loopback_detection_id,
  11694.                    1)
  11695.            /*  NULL) */
  11696.  
  11697.        IF @@ERROR <> 0
  11698.            BEGIN
  11699.                 if @@trancount > 0
  11700.                 begin
  11701.                     ROLLBACK TRAN  addsubscription
  11702.                     commit tran
  11703.                 end
  11704.                 RAISERROR (14057, 16, -1)
  11705.                 RETURN (1)
  11706.            END
  11707.         END
  11708.     ELSE
  11709.        BEGIN
  11710.           RAISERROR (14058, 16, -1)
  11711.           if @@trancount > 0
  11712.             begin
  11713.                 ROLLBACK TRAN  addsubscription
  11714.                 commit tran
  11715.             end
  11716.           RETURN (1)
  11717.        END
  11718.  
  11719.     /*
  11720.     ** If the @status was not provided determine the default value.
  11721.     ** If the @sync_type = 'none' then the subscription defaults to 'active'.
  11722.     ** Else the subscription defaults to 'subscribed'.
  11723.     */
  11724.     IF @status IS NULL
  11725.     BEGIN
  11726.         IF @sync_typeid = @none    
  11727.             SELECT @status = 'active'
  11728.         ELSE
  11729.             SELECT @status = 'subscribed'
  11730.     END
  11731.  
  11732.  
  11733.     /*
  11734.     ** Set publication subscription status.
  11735.     */
  11736.     EXEC @retcode = dbo.sp_changesubstatus
  11737.     @publication = @publication,
  11738.     @article     = @article,
  11739.     @subscriber  = @subscriber,
  11740.     @status      = @status,
  11741.     @destination_db = @destination_db,
  11742.     
  11743.     @frequency_type  = @frequency_type,
  11744.     @frequency_interval  = @frequency_interval,
  11745.     @frequency_relative_interval  = @frequency_relative_interval,
  11746.     @frequency_recurrence_factor  = @frequency_recurrence_factor,
  11747.     @frequency_subday  = @frequency_subday,
  11748.     @frequency_subday_interval  = @frequency_subday_interval,
  11749.     @active_start_time_of_day  = @active_start_time_of_day,
  11750.     @active_end_time_of_day  = @active_end_time_of_day,
  11751.     @active_start_date  = @active_start_date,
  11752.     @active_end_date  = @active_end_date,
  11753.     @optional_command_line = @optional_command_line,
  11754.     @distribution_jobid = @distribution_jobid OUTPUT,
  11755.     @offloadagent = @offloadagent,
  11756.     @offloadserver = @offloadserver,
  11757.     @dts_package_name = @dts_package_name,
  11758.     @dts_package_password = @dts_package_enc_password,
  11759.     @dts_package_location = @dts_package_location_id,
  11760.     @distribution_job_name = @distribution_job_name  
  11761.     
  11762.     IF @@error <> 0 OR @retcode <> 0
  11763.     BEGIN
  11764.         if @@trancount > 0
  11765.         begin
  11766.             ROLLBACK TRAN  addsubscription
  11767.             commit tran
  11768.         end
  11769.        RAISERROR (14057, 16, -1)
  11770.        RETURN (1)
  11771.     END
  11772.  
  11773.     UPDATE syssubscriptions SET 
  11774.         distribution_jobid = @distribution_jobid where
  11775.         artid = @artid AND
  11776.         srvid = @srvid AND
  11777.         dest_db = @destination_db            
  11778.  
  11779.     IF @@error <> 0
  11780.     BEGIN
  11781.         if @@trancount > 0
  11782.         begin
  11783.             ROLLBACK TRAN  addsubscription
  11784.             commit tran
  11785.         end
  11786.        RETURN (1)
  11787.     END
  11788.  
  11789.  
  11790.     /*
  11791.     ** If possible, activate the real subscriptions on immediate_sync publication
  11792.     ** immediately. Also, activate the virtual subscriptions on 
  11793.     ** anonymous publications immediately.
  11794.     ** We change the subscription status from 'subscribed' to 'active' so that 
  11795.     ** sp_MSupdate_subscription will be called, which will set the subscription's
  11796.     ** xactid_ts to the snapshot xactid_ts of virtual subscriptions. This means that
  11797.     ** we have to call sp_changesubstatus again here. We can not combine two calls 
  11798.     ** into ONE !!!
  11799.     **
  11800.     ** Activate the subscription immediately if 
  11801.     ** 1. The publication is immediate_sync type
  11802.     ** 2. sync_type is 'automatic'
  11803.     ** AND
  11804.     ** 1. The subscription is real
  11805.     ** 2. The snapshot has completed once
  11806.     ** 3. The subscription is the last subscription added to the publication (subscription for
  11807.     ** the last article). This is to guarantee the subscription status of all the articles
  11808.     ** in the publication be activate in one transaction at the distributor. This is
  11809.     ** to prevent the distribution agent from picking up partial subscriptions. 
  11810.     ** Note that this SP will be called with @article = 'all'
  11811.     ** OR
  11812.     ** 1. The publication is active
  11813.     ** 2. The publication is allow_anonymous
  11814.     ** 3. The subscription is virtual
  11815.     ** 
  11816.     */
  11817.     
  11818.     IF  @sync_typeid = @automatic AND @immediate_sync = 1 AND
  11819.         
  11820.         ((@srvid <> @virtual_id AND 
  11821.         @immediate_sync_ready = 1 AND
  11822.         NOT EXISTS (select * from sysextendedarticlesview art where
  11823.                     art.pubid = @pubid and
  11824.                     not exists (select * from syssubscriptions sub
  11825.                         where sub.artid = art.artid and
  11826.                               sub.srvid = @srvid and
  11827.                               sub.dest_db = @destination_db))) OR
  11828.  
  11829.         (@pubstatus = 1 and @srvid = @virtual_id and @allow_anonymous = 1))
  11830.     BEGIN
  11831.         DECLARE @article_ex sysname
  11832.         IF @srvid <> @virtual_id
  11833.             SELECT @article_ex = '%'
  11834.         ELSE
  11835.             SELECT @article_ex = @article
  11836.  
  11837.         /*
  11838.         ** Set publication subscription status.
  11839.         */
  11840.         EXEC @retcode = dbo.sp_changesubstatus
  11841.         @publication = @publication,
  11842.         @article     = @article_ex,
  11843.         @subscriber  = @subscriber,
  11844.         @status      = 'active',
  11845.         @destination_db = @destination_db,
  11846.         @offloadagent = @offloadagent,
  11847.         @offloadserver = @offloadserver
  11848.  
  11849.         IF @@error <> 0 OR @retcode <> 0
  11850.         BEGIN
  11851.             if @@trancount > 0
  11852.             begin
  11853.                 ROLLBACK TRAN  addsubscription
  11854.                 commit tran
  11855.             end
  11856.            RAISERROR (14057, 16, -1)
  11857.            RETURN (1)
  11858.         END
  11859.     END
  11860.  
  11861.     /* Conditional support for MobileSync */
  11862.     if LOWER(@enabled_for_syncmgr) = 'true'
  11863.     BEGIN
  11864.         /* MobileSync Support */
  11865.         declare @distributor_server                 sysname
  11866.         declare @distributor_security_mode          int
  11867.         declare @distributor_login                  sysname
  11868.         declare @distributor_password               sysname
  11869.         declare @publisher_db sysname
  11870.         
  11871.         set @publisher_db = DB_NAME()
  11872.         /* 
  11873.         ** The registry entry needs to be created only for push subscriptions -  
  11874.         ** i.e - need not be called when a pull subscription is created at the 
  11875.         ** subscriber and sp_addmergesubscription is being called then.
  11876.         */
  11877.         IF LOWER(@subscription_type) = 'push'
  11878.         BEGIN
  11879.             EXECUTE @retcode = dbo.sp_helpdistributor
  11880.                 @distributor = @distributor_server OUTPUT               /* Distributor RPC server name */
  11881.  
  11882.             IF @@ERROR <> 0 or @retcode <> 0
  11883.                 BEGIN
  11884.                     if @@trancount > 0
  11885.                         ROLLBACK TRAN  addsubscription
  11886.                     RAISERROR (14057, 16, -1)
  11887.                     RETURN (1)
  11888.                 END
  11889.  
  11890.             -- Always use integrated security on winNT
  11891.             if (@platform_nt = platform() & @platform_nt )
  11892.                 begin
  11893.                     set @distributor_security_mode = 1
  11894.                 end
  11895.             -- For Win9x the dist publisher and distributor are the same machine                
  11896.             else
  11897.                 begin
  11898.                     select  @distributor_security_mode = 0,
  11899.                         @distributor_login  = login,
  11900.                         @distributor_password = password
  11901.                     from msdb..MSdistpublishers where UPPER(name) = UPPER(@@servername) collate database_default
  11902.                 end
  11903.  
  11904.  
  11905.             /* Call sp_MSregistersubscription so that the subscription can be synchronized via Onestop etc. */
  11906.             declare @subscription_id uniqueidentifier
  11907.             set @subscription_id = convert(uniqueidentifier, @distribution_jobid)
  11908.             exec @retcode = dbo.sp_MSregistersubscription @replication_type = 1,
  11909.                                     @publisher = @@SERVERNAME,
  11910.                                     @publisher_db = @publisher_db,
  11911.                                     @publication = @publication,
  11912.                                     @subscriber = @subscriber,
  11913.                                     @subscriber_db = @destination_db,
  11914.                                     @distributor = @distributor_server,
  11915.                                     @distributor_security_mode = @distributor_security_mode,
  11916.                                     @distributor_login = @distributor_login,
  11917.                                     @distributor_password = @distributor_password,
  11918.                                     @subscription_id = @subscription_id,
  11919.                                     @independent_agent = @independent_agent_id,
  11920.                                     @subscription_type = @subscription_type_id
  11921.  
  11922.  
  11923.             IF @@ERROR <> 0 or @retcode <> 0
  11924.                 BEGIN
  11925.                     if @@trancount > 0
  11926.                         ROLLBACK TRAN  addsubscription
  11927.                     RAISERROR (14057, 16, -1)
  11928.                     RETURN (1)
  11929.                 END
  11930.         END
  11931.     END
  11932.     COMMIT TRAN
  11933. go
  11934.  
  11935. EXEC dbo.sp_MS_marksystemobject sp_addsubscription
  11936. GO
  11937.  
  11938. print ''
  11939. print 'Creating procedure sp_MSchangeschemaarticle'
  11940. GO
  11941. CREATE PROCEDURE sp_MSchangeschemaarticle (
  11942.     @pubid int,
  11943.     @artid int,
  11944.     @property sysname,
  11945.     @value nvarchar(255)
  11946.     ) AS
  11947.     SET NOCOUNT ON
  11948.     DECLARE @retcode int
  11949.     DECLARE @pre_creation_cmdid tinyint
  11950.     DECLARE @statusid int
  11951.     DECLARE @schema_option_table_created bit
  11952.     DECLARE @creation_script nvarchar(255)
  11953.     DECLARE @type tinyint
  11954.     DECLARE @schema_option binary(8)
  11955.     DECLARE @valid_schema_options int
  11956.  
  11957.     SELECT @type = type 
  11958.       FROM sysextendedarticlesview
  11959.      WHERE artid = @artid
  11960.        AND pubid = @pubid 
  11961.  
  11962.     SELECT @schema_option_table_created = 0
  11963.  
  11964.     /* 
  11965.     ** The pubid and artid passed into this procedure from sp_changearticle
  11966.     ** have to be valid by now.
  11967.     */
  11968.     
  11969.     /*
  11970.     ** Parameter check: @property
  11971.     */
  11972.     SELECT @property = LOWER(@property)
  11973.     IF @property NOT IN ('description',
  11974.                          'dest_object',
  11975.                          'creation_script',
  11976.                          'pre_creation_cmd',
  11977.                          'schema_option',
  11978.                          'destination_owner')
  11979.     BEGIN
  11980.         RAISERROR(21224, 16, -1, @property)
  11981.         RETURN (1)
  11982.     END
  11983.                          
  11984.     -- Since all property changes will take the form of 
  11985.     -- simple update stataments, no transaction will be 
  11986.     -- started. 
  11987.  
  11988.     IF @property = N'description'
  11989.     BEGIN
  11990.         UPDATE sysschemaarticles 
  11991.            SET description = @value
  11992.          WHERE artid = @artid
  11993.            AND pubid = @pubid
  11994.  
  11995.         IF @@ERROR <> 0
  11996.             RETURN (1)
  11997.     END
  11998.     ELSE IF @property = N'dest_object'
  11999.     BEGIN
  12000.         UPDATE sysschemaarticles
  12001.            SET dest_object = @value
  12002.          WHERE artid = @artid
  12003.            AND pubid = @pubid 
  12004.  
  12005.         IF @@ERROR <> 0
  12006.             RETURN (1)
  12007.     END
  12008.     ELSE IF @property = N'creation_script'
  12009.     BEGIN
  12010.         UPDATE sysschemaarticles 
  12011.            SET creation_script = @value
  12012.          WHERE artid = @artid
  12013.            AND pubid = @pubid
  12014.  
  12015.         IF @@ERROR <> 0
  12016.             RETURN (1)
  12017.     END
  12018.     ELSE IF @property = N'pre_creation_cmd'
  12019.     BEGIN
  12020.         /* 
  12021.         ** Validate the given value for
  12022.         ** the property. It has to be either 
  12023.         ** 'none' or 'drop' case-insensitive.
  12024.         */
  12025.         SELECT @value = LOWER(@value)
  12026.         IF @value NOT IN ('none', 'drop')
  12027.         BEGIN
  12028.             RAISERROR(21223, 16, -1)
  12029.             RETURN (1)
  12030.         END
  12031.  
  12032.         IF @value = N'none'
  12033.             SELECT @pre_creation_cmdid = 0
  12034.         ELSE IF @value = N'drop'
  12035.             SELECT @pre_creation_cmdid = 1
  12036.         
  12037.         UPDATE sysschemaarticles
  12038.            SET pre_creation_cmd = @pre_creation_cmdid
  12039.          WHERE artid = @artid
  12040.            AND pubid = @pubid
  12041.         
  12042.         IF @@ERROR <> 0
  12043.             RETURN (1)
  12044.  
  12045.     END
  12046.     ELSE IF @property = N'schema_option'    
  12047.     BEGIN
  12048.         
  12049.         IF @value IS NULL
  12050.         BEGIN
  12051.             RAISERROR(14146, 16,1)
  12052.             RETURN (1)
  12053.         END
  12054.  
  12055.         CREATE TABLE #tab_changeschemaarticle (value varbinary(8) NULL)
  12056.         IF @@ERROR <> 0
  12057.         BEGIN
  12058.            RETURN (1)
  12059.         END
  12060.  
  12061.         EXEC ('insert #tab_changeschemaarticle values (' + 
  12062.             @value + ')')
  12063.  
  12064.         IF @@ERROR <> 0
  12065.         BEGIN
  12066.             DROP TABLE #tab_changeschemaarticle 
  12067.             RETURN (1)
  12068.         END
  12069.         
  12070.         SELECT @schema_option = fn_replprepadbinary8(value) 
  12071.           FROM #tab_changeschemaarticle
  12072.         /*
  12073.         ** schema_option can only contain the bits 0x0000000000000001 and
  12074.         ** 0x0000000000002000
  12075.         ** for schema only articles except view. View articles can contain 
  12076.         ** the options 0x0000000000000010, 0x0000000000000020, 
  12077.         ** and 0x0000000000000100 in addition to the aforementioned options.
  12078.         */
  12079.         IF @type = 0x40
  12080.         BEGIN
  12081.  
  12082.             -- Since only the lower 32 bits of @schema_option are
  12083.             -- currently used, the following check is sufficient.
  12084.             -- Note that @schema_option should have been padded by now.
  12085.             DECLARE @schema_option_lodword int
  12086.             SELECT @valid_schema_options = 0x2151
  12087.             SELECT @schema_option_lodword = fn_replgetbinary8lodword(@schema_option)
  12088.             IF (@schema_option_lodword & ~@valid_schema_options) <> 0
  12089.             BEGIN
  12090.                 RAISERROR (21229, 16, -1)
  12091.                 RETURN (1)
  12092.             END
  12093.         END
  12094.         ELSE IF @schema_option NOT IN (0x0000000000000000,
  12095.                                        0x0000000000000001,
  12096.                                        0x0000000000002000,
  12097.                                        0x0000000000002001)
  12098.         BEGIN
  12099.             DROP TABLE #tab_changeschemaarticle
  12100.             RAISERROR (21222, 16, -1)
  12101.             RETURN (1)
  12102.         END 
  12103.  
  12104.         IF EXISTS (SELECT * FROM #tab_changeschemaarticle
  12105.                     WHERE value = 0x0000000000000000)
  12106.         BEGIN
  12107.         
  12108.             SELECT @creation_script = NULL
  12109.             SELECT @creation_script = creation_script
  12110.               FROM sysschemaarticles
  12111.              WHERE artid = @artid
  12112.                AND pubid = @pubid
  12113. /*            
  12114.             IF @creation_script IS NULL OR
  12115.                @creation_script = N''
  12116.             BEGIN
  12117.                 RAISERROR(21218, 16, -1)
  12118.                 DROP TABLE #tab_changeschemaarticle
  12119.                 RETURN (1)
  12120.             END
  12121. */
  12122.         END
  12123.             
  12124.         UPDATE sysschemaarticles
  12125.            SET schema_option = tab.value
  12126.           FROM #tab_changeschemaarticle tab
  12127.          WHERE artid = @artid 
  12128.            AND pubid = @pubid         
  12129.             
  12130.         IF @@ERROR <> 0
  12131.         BEGIN
  12132.             DROP TABLE #tab_changeschemaarticle
  12133.             RETURN (1)
  12134.         END    
  12135.  
  12136.         DROP TABLE #tab_changeschemaarticle
  12137.  
  12138.         IF @@ERROR <> 0
  12139.             RETURN (1)
  12140.     END
  12141.     ELSE IF @property = N'destination_owner'
  12142.     BEGIN
  12143.         
  12144.         UPDATE sysschemaarticles
  12145.            SET dest_owner = @value
  12146.          WHERE artid = @artid
  12147.            AND pubid = @pubid
  12148.  
  12149.         IF @@ERROR <> 0
  12150.             RETURN (1)
  12151.     END    
  12152.  
  12153.     RAISERROR (14025, 10, -1)
  12154.     RETURN (0)
  12155. GO
  12156.  
  12157. EXEC dbo.sp_MS_marksystemobject sp_MSchangeschemaarticle
  12158. GO
  12159.  
  12160. print ''
  12161. print 'Creating procedure sp_changearticle'
  12162. GO
  12163. CREATE PROCEDURE sp_changearticle (
  12164.     @publication sysname = NULL,        /* Publication name */
  12165.     @article sysname = NULL,            /* Article name */
  12166.     @property nvarchar(20) = NULL,      /* The property to change */
  12167.     @value nvarchar(255) = NULL,        /* The new property value */
  12168.     @force_invalidate_snapshot bit = 0,    /* Force invalidate existing snapshot */
  12169.     @force_reinit_subscription bit = 0    /* Force reinit subscription */
  12170. ) AS
  12171. BEGIN
  12172.  
  12173.     SET NOCOUNT ON
  12174.  
  12175.     /*
  12176.     ** Declarations.
  12177.     */
  12178.  
  12179.     DECLARE @artid int
  12180.             ,@cmd1 nvarchar(512)
  12181.             ,@cmd2 nvarchar(512)
  12182.             ,@db sysname
  12183.             ,@filter int
  12184.             ,@object sysname
  12185.             ,@owner sysname
  12186.             ,@pubid int
  12187.             ,@retcode int
  12188.             ,@site sysname
  12189.             ,@sync_objid int
  12190.             ,@typeid tinyint
  12191.             ,@old_typeid tinyint
  12192.             ,@precmdid tinyint
  12193.             ,@active tinyint
  12194.             ,@virtual_id smallint
  12195.             ,@article_type tinyint
  12196.  
  12197.             ,@objid    int
  12198.             ,@objtype  nchar(2)
  12199.             ,@old_filter_name sysname
  12200.  
  12201.             ,@distributor sysname
  12202.             ,@distribdb sysname
  12203.             ,@dbname sysname
  12204.             ,@distproc nvarchar (255)
  12205.             ,@dts_part nvarchar(50)
  12206.             ,@no_dts_part nvarchar(50)
  12207.             ,@backward_comp_level int
  12208.             ,@allow_dts bit
  12209.             ,@allow_queued_tran bit
  12210.  
  12211.     select @backward_comp_level = 10 -- default to sphinx
  12212.             ,@dts_part = N'dts horizontal partitions'
  12213.             ,@no_dts_part = N'no dts horizontal partitions'
  12214.             ,@active = 2
  12215.             ,@virtual_id = -1
  12216.  
  12217.     /*
  12218.     ** Security Check
  12219.     */
  12220.     exec @retcode = dbo.sp_MSreplcheck_publish
  12221.     if @@ERROR <> 0 or @retcode <> 0
  12222.         return(1)
  12223.  
  12224.     /*
  12225.     ** Check to see if the database has been activated for publication.
  12226.     */
  12227.  
  12228.     IF (SELECT category & 1
  12229.           FROM master..sysdatabases
  12230.          WHERE name = DB_NAME() collate database_default) = 0
  12231.  
  12232.     BEGIN
  12233.             RAISERROR (14013, 16, -1)
  12234.             RETURN (1)
  12235.         END
  12236.  
  12237.  
  12238.     /*
  12239.     ** Parameter Check:  @publication.
  12240.     ** Make sure that the publication exists.
  12241.     */
  12242.  
  12243.     IF @publication IS NULL
  12244.         BEGIN
  12245.             RAISERROR (14043, 16, -1, '@publication')
  12246.             RETURN (1)
  12247.         END
  12248.  
  12249.     EXECUTE @retcode = dbo.sp_validname @publication
  12250.  
  12251.     IF @@ERROR <> 0 OR @retcode <> 0
  12252.     RETURN (1)
  12253.  
  12254.     SELECT @pubid = pubid
  12255.         ,@allow_dts = allow_dts
  12256.         ,@allow_queued_tran = allow_queued_tran
  12257.     FROM syspublications 
  12258.     WHERE name = @publication
  12259.  
  12260.     IF @pubid IS NULL
  12261.         BEGIN
  12262.             RAISERROR (20026, 11, -1, @publication)
  12263.             RETURN (1)
  12264.         END
  12265.  
  12266.     /*
  12267.     ** Check to see that the article exists in sysextendedarticlesview.
  12268.     ** Fetch the article identification number.
  12269.     */
  12270.  
  12271.     IF @article IS NULL
  12272.         BEGIN
  12273.             RAISERROR (14043, 16, -1, '@article')
  12274.             RETURN (1)
  12275.         END
  12276.  
  12277.     /*
  12278.     EXECUTE @retcode = dbo.sp_validname @article
  12279.  
  12280.     IF @retcode <> 0
  12281.     RETURN (1)
  12282.     */
  12283.     SELECT @artid = artid, @article_type = type, @objid = objid 
  12284.       FROM sysextendedarticlesview
  12285.      WHERE name = @article
  12286.        AND pubid = @pubid
  12287.     IF @artid IS NULL
  12288.         BEGIN
  12289.             RAISERROR (20027, 11, -1, @article)
  12290.             RETURN (1)
  12291.         END
  12292.  
  12293.  
  12294.     /*
  12295.     ** Get the object id and type from sysobjects
  12296.     */
  12297.  
  12298.     SELECT @objtype = type
  12299.        FROM sysobjects
  12300.        WHERE id = @objid
  12301.  
  12302.     IF @objtype IS NULL
  12303.     BEGIN
  12304.         RAISERROR( 20027, 11, -1, @article )
  12305.         RETURN( 1 )
  12306.     END
  12307.  
  12308.     /*
  12309.     ** Parameter Check:  @property.
  12310.     ** If the @property parameter is NULL, print the options.
  12311.     */
  12312.  
  12313.     IF @property IS NULL
  12314.         BEGIN
  12315.             CREATE TABLE #tab1 (properties sysname collate database_default not null)
  12316.             INSERT INTO #tab1 VALUES ('description')
  12317.             INSERT INTO #tab1 VALUES ('sync_object (log based article only)')
  12318.             INSERT INTO #tab1 VALUES ('type')
  12319.             INSERT INTO #tab1 VALUES ('ins_cmd (log based article only)')
  12320.             INSERT INTO #tab1 VALUES ('del_cmd (log based article only)')
  12321.             INSERT INTO #tab1 VALUES ('upd_cmd (log based article only)')
  12322.             INSERT INTO #tab1 VALUES ('filter (log based article only)')
  12323.             INSERT INTO #tab1 VALUES ('dest_table (log based article only)')
  12324.             INSERT INTO #tab1 VALUES ('dest_object')
  12325.             INSERT INTO #tab1 VALUES ('creation_script')
  12326.             INSERT INTO #tab1 VALUES ('pre_creation_cmd')
  12327.             INSERT INTO #tab1 VALUES ('status')
  12328.             INSERT INTO #tab1 VALUES ('schema_option')
  12329.             INSERT INTO #tab1 VALUES ('destination_owner')
  12330.                INSERT INTO #tab1 VALUES ('pub_identity_range (log based article only)')
  12331.             INSERT INTO #tab1 VALUES ('identity_range (log based article only)')
  12332.             INSERT INTO #tab1 VALUES ('threshold (log based article only)')
  12333.             PRINT ''
  12334.             SELECT * FROM #tab1
  12335.             RETURN (0)
  12336.         END
  12337.  
  12338.     /*
  12339.     ** At this point, we have completed all the validations and 
  12340.     ** preprocessings common to both regular and schema only articles 
  12341.     ** so we call a different proceudre here to handle the schema only
  12342.     ** articles differently.
  12343.     */
  12344.     
  12345.     IF @article_type in (0x20, 0x40, 0x80)
  12346.     BEGIN
  12347.         EXEC @retcode = sp_MSchangeschemaarticle 
  12348.                 @pubid = @pubid,
  12349.                 @artid = @artid,
  12350.                 @property = @property,
  12351.                 @value = @value    
  12352.         RETURN @retcode
  12353.     END  
  12354.  
  12355.     IF @objtype = 'U' AND LOWER(@property) NOT IN ('description',
  12356.                                                    'sync_object',
  12357.                                                    'type',
  12358.                                                    'ins_cmd',
  12359.                                                    'del_cmd',
  12360.                                                    'upd_cmd',
  12361.                                                    'filter',
  12362.                                                    'dest_table',
  12363.                                                    'dest_object',
  12364.                                                    'creation_script',
  12365.                                                    'pre_creation_cmd',
  12366.                                                    'status',
  12367.                                                    'schema_option',
  12368.                                                    'destination_owner',
  12369.                                                     'pub_identity_range',
  12370.                                                     'identity_range',
  12371.                                                     'threshold')
  12372.         BEGIN
  12373.             RAISERROR (21183, 16, -1, @property)
  12374.             RETURN (1)
  12375.         END
  12376.  
  12377.     IF @objtype = 'P' AND LOWER(@property) NOT IN ('description',
  12378.                                                    'dest_object',
  12379.                                                    'dest_table',
  12380.                                                    'creation_script',
  12381.                                                    'pre_creation_cmd',
  12382.                                                    'schema_option',
  12383.                                                    'destination_owner')
  12384.         BEGIN
  12385.             RAISERROR (14110, 16, -1)
  12386.             RETURN (1)
  12387.         END
  12388.  
  12389.  
  12390.     /* dest_object and 'dest_table' are same */
  12391.     IF LOWER(@property) = 'dest_object'
  12392.         SELECT @property = 'dest_table' 
  12393.  
  12394.     
  12395.     IF (@allow_dts = 1 or @allow_queued_tran = 1) and LOWER(@property) IN ('ins_cmd', 'del_cmd', 'upd_cmd' )
  12396.     begin
  12397.         raiserror(21175, 16, -1)
  12398.         return (1)
  12399.     end
  12400.     
  12401.     /*
  12402.     ** Check to make sure that we have a valid type for status
  12403.     */
  12404.     IF LOWER(@property) = 'status'
  12405.     BEGIN
  12406.         IF LOWER(@value) IN ('not owner qualified', 'owner qualified')
  12407.         BEGIN
  12408.             RAISERROR (21023, 16, -1,@value)
  12409.             RETURN (1)
  12410.         END
  12411.  
  12412.         IF LOWER(@value) NOT IN ('no column names', 'include column names', 'string literals', 'parameters',
  12413.             @dts_part, @no_dts_part )
  12414.         BEGIN
  12415.             RAISERROR (14097, 16, -1)
  12416.             RETURN (1)
  12417.         END
  12418.  
  12419.         IF    LOWER(@value) in (@dts_part,@no_dts_part)
  12420.         begin
  12421.             if @allow_dts = 0
  12422.             begin
  12423.                 -- Invalid status for non dts pub
  12424.                 raiserror(20592, 16, -1)
  12425.                 RETURN (1)
  12426.             end
  12427.         end
  12428.         else
  12429.         begin
  12430.             if @allow_dts = 1
  12431.             begin
  12432.                 -- Invalid status for dts pub
  12433.                 raiserror(20591, 16, -1)
  12434.                 RETURN (1)
  12435.             end
  12436.         end
  12437.     end
  12438.     
  12439.     IF LOWER(@property) IN ( 'ins_cmd', 'del_cmd', 'upd_cmd' )
  12440.     BEGIN
  12441.         if exists (select * from syspublications 
  12442.         where
  12443.         pubid = @pubid and sync_method = 3) and lower(@value) not like '%call%'
  12444.         BEGIN
  12445.             RAISERROR( 21154, 16, -1, @article )
  12446.             return 1
  12447.         END
  12448.     END
  12449.  
  12450.     declare @need_new_snapshot bit
  12451.         ,@need_reinit_subscription bit
  12452.  
  12453.     select @need_new_snapshot = 0
  12454.     select @need_reinit_subscription = 0
  12455.  
  12456.     if LOWER(@property) in ( N'ins_cmd', N'del_cmd', N'upd_cmd', 
  12457.         N'dest_table', N'destination_owner' ,N'type',N'filter',  
  12458.         N'pre_creation_cmd', N'schema_option') or 
  12459.         (LOWER(@property) = 'status' and LOWER(@value) in (@dts_part,
  12460.         @no_dts_part))
  12461.     begin
  12462.         select @need_new_snapshot = 1
  12463.         select @need_reinit_subscription = 1
  12464.     end
  12465.     else if LOWER(@property) in ('sync_object',
  12466.         'creation_script')
  12467.     begin
  12468.         select @need_new_snapshot = 1
  12469.     end
  12470.  
  12471.     -- Have to call this stored procedure to invalidate existing snapshot or reint
  12472.     -- subscriptions if needed
  12473.     EXECUTE @retcode  = dbo.sp_MSreinit_article
  12474.         @publication = @publication, 
  12475.         @article = @article,
  12476.         @need_new_snapshot = @need_new_snapshot,
  12477.         @need_reinit_subscription = @need_reinit_subscription
  12478.         ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  12479.         ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  12480.         ,@check_only = 1
  12481.     IF @@ERROR <> 0 OR @retcode <> 0
  12482.         return(1)
  12483.  
  12484.     /*
  12485.     ** Change the property.
  12486.     */
  12487.  
  12488.     begin tran
  12489.     save TRAN sp_changearticle
  12490.  
  12491.         IF LOWER(@property) IN ( 'description', 'ins_cmd', 'del_cmd', 'upd_cmd', 'dest_table', 'creation_script', 'dest_object')
  12492.             BEGIN
  12493.  
  12494.  
  12495.             /*
  12496.             ** Check the validity of the destination object.  NULL should
  12497.             ** get converted to the source object name.  Destination object
  12498.             ** names can be owner qualified, but not database qualified.
  12499.             */
  12500.  
  12501.             IF LOWER(@property) = 'dest_table' OR LOWER(@property) = 'dest_object'
  12502.                 BEGIN
  12503.                     IF @value IS NULL
  12504.                         SELECT @value = object_name(objid)
  12505.                           FROM sysarticles
  12506.                          WHERE artid = @artid
  12507.                            AND pubid = @pubid
  12508.                 END
  12509.  
  12510.             SELECT @cmd1 = 'UPDATE sysarticles '
  12511.  
  12512.             IF @value IS NULL
  12513.             BEGIN
  12514.                     SELECT @cmd1 = @cmd1 + '   SET ' + LOWER(@property) + ' = NULL'
  12515.                 SELECT @cmd2 = ' WHERE artid = ' + STR(@artid)
  12516.                 SELECT @cmd2 = @cmd2 + '   AND pubid = ' + STR(@pubid)
  12517.                 EXECUTE (@cmd1 + @cmd2)
  12518.             END
  12519.             ELSE
  12520.             BEGIN
  12521.                 
  12522.                 SELECT @cmd1 = @cmd1 + '   SET ' + LOWER(@property) + ' = ''' + @value + ''''
  12523.                 SELECT @cmd2 = ' WHERE artid = ' + STR(@artid)
  12524.                 SELECT @cmd2 = @cmd2 + '   AND pubid = ' + STR(@pubid)
  12525.                 EXECUTE (@cmd1 + @cmd2)
  12526.             END
  12527.  
  12528.             IF LOWER(@property) = 'upd_cmd'
  12529.             BEGIN
  12530.                 IF ( 0 <> ( SELECT PATINDEX( '%[789].[0-9]%', @@version ) ) ) OR
  12531.                    ( 0 <> ( SELECT PATINDEX( '%[1-9][0-9].[0-9]%', @@version ) ) )
  12532.                 BEGIN
  12533.                     exec dbo.sp_MSsetfilteredstatus @objid
  12534.                 END
  12535.  
  12536.             END
  12537.  
  12538.             IF @@ERROR <> 0 
  12539.                 BEGIN
  12540.                     if @@trancount > 0
  12541.                     begin
  12542.                         ROLLBACK TRAN sp_changearticle
  12543.                         commit tran
  12544.                     end
  12545.                     RETURN (1)
  12546.                 END
  12547.             END
  12548.  
  12549.         IF LOWER(@property) = 'sync_object'
  12550.             BEGIN
  12551.  
  12552.                 /*
  12553.                 ** Check for a valid synchronization object.
  12554.                 */
  12555.  
  12556.                 IF @value IS NULL
  12557.                     BEGIN
  12558.                         RAISERROR (14043, 16, -1, '@value')
  12559.                         if @@trancount > 0
  12560.                         begin
  12561.                             ROLLBACK TRAN sp_changearticle
  12562.                             commit tran
  12563.                         end
  12564.                         RETURN (1)
  12565.                     END
  12566.  
  12567.                 IF @value LIKE '%.%.%' OR @value LIKE '%.%'
  12568.                 BEGIN
  12569.                   select @object = PARSENAME( @value, 1 )
  12570.                   select @owner = PARSENAME(  @value, 2 )
  12571.                   select @db = PARSENAME(  @value, 3 )
  12572.                   select @site = PARSENAME(  @value, 4 )
  12573.  
  12574.                   if @object IS NULL
  12575.                         return 1
  12576.                 END
  12577.  
  12578.  
  12579.                 SELECT @sync_objid = OBJECT_ID(@value)
  12580.                 IF @sync_objid IS NULL
  12581.                     BEGIN
  12582.                         RAISERROR (15001, 11, -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 NOT EXISTS (SELECT *
  12592.                                  FROM sysobjects
  12593.                                 WHERE type IN ('U', 'V')
  12594.                                   AND id = @sync_objid)
  12595.  
  12596.                     BEGIN
  12597.                         RAISERROR (14031, 16, -1)
  12598.                         if @@trancount > 0
  12599.                         begin
  12600.                             ROLLBACK TRAN sp_changearticle
  12601.                             commit tran
  12602.                         end
  12603.                         RETURN (1)
  12604.                     END
  12605.  
  12606.                 /*
  12607.                 ** Update the article with the new synchronization object.
  12608.                 */
  12609.  
  12610.                 UPDATE sysarticles
  12611.                    SET sync_objid = @sync_objid
  12612.                  WHERE artid = @artid
  12613.                    AND pubid = @pubid
  12614.  
  12615.                 IF @@ERROR <> 0 
  12616.                 BEGIN
  12617.                     if @@trancount > 0
  12618.                     begin
  12619.                         ROLLBACK TRAN sp_changearticle
  12620.                         commit tran
  12621.                     end
  12622.                     RETURN (1)
  12623.                 END
  12624.  
  12625.             END
  12626.  
  12627.         IF LOWER(@property) = 'type'
  12628.             BEGIN
  12629.  
  12630.                 /*
  12631.                 ** Check to make sure that we have a valid type.
  12632.                 */
  12633.  
  12634.             IF LOWER(@value) NOT IN ('logbased', 'logbased manualfilter', 'logbased manualview', 'logbased manualboth')
  12635.                     BEGIN
  12636.                         RAISERROR (14023, 16, -1)
  12637.                         if @@trancount > 0
  12638.                         begin
  12639.                             ROLLBACK TRAN sp_changearticle
  12640.                             commit tran
  12641.                         end
  12642.                         RETURN (1)
  12643.                     END
  12644.  
  12645.                 /*
  12646.                 ** Determine the integer value for the type.
  12647.                 */
  12648.             IF LOWER(@value) IN ('logbased', 'indexed view logbased')
  12649.             SELECT @typeid = 1
  12650.             ELSE IF LOWER(@value) IN ('logbased manualfilter', 'indexed view logbased manualfilter')
  12651.             SELECT @typeid = 3
  12652.             ELSE IF LOWER(@value) IN ('logbased manualview', 'indexed view logbased manualview')
  12653.             SELECT @typeid = 5
  12654.             ELSE IF LOWER(@value) IN ('logbased manualboth', 'indexed view logbased manualboth')
  12655.             SELECT @typeid = 7
  12656.  
  12657.                 /*
  12658.                 ** Update the article with the new type.
  12659.                 */
  12660.  
  12661.                 UPDATE sysarticles
  12662.                    SET type = @typeid
  12663.                  WHERE artid = @artid
  12664.                    AND pubid = @pubid
  12665.  
  12666.                 IF @@ERROR <> 0 
  12667.                 BEGIN
  12668.                     if @@trancount > 0
  12669.                     begin   
  12670.                         ROLLBACK TRAN sp_changearticle
  12671.                         commit tran
  12672.                     end
  12673.                     RETURN (1)
  12674.                 END
  12675.  
  12676.  
  12677.             END
  12678.  
  12679.         IF LOWER(@property) = 'filter'
  12680.             BEGIN
  12681.  
  12682.                 /*
  12683.                 ** Check for a valid filter value.
  12684.                 */
  12685.  
  12686.                 IF @value IS NOT NULL
  12687.                     BEGIN
  12688.  
  12689.                         IF @value LIKE '%.%.%' OR @value LIKE '%.%'
  12690.                         BEGIN
  12691.                            select @object = PARSENAME( @value, 1 )
  12692.                            select @owner = PARSENAME(  @value, 2 )
  12693.                            select @db = PARSENAME(  @value, 3 )
  12694.                            select @site = PARSENAME(  @value, 4 )
  12695.  
  12696.                            if @object IS NULL
  12697.                                  return 1
  12698.                         END
  12699.  
  12700.                     END
  12701.  
  12702.                 SELECT @filter = OBJECT_ID(@value)
  12703.  
  12704.                 IF @value IS NOT NULL
  12705.                     BEGIN
  12706.  
  12707.                         IF @filter IS NULL
  12708.                             BEGIN
  12709.                                 RAISERROR (15001, 11, -1, @value)
  12710.                                 if @@trancount > 0
  12711.                                 begin
  12712.                                     ROLLBACK TRAN sp_changearticle
  12713.                                     commit tran
  12714.                                 end
  12715.                                 RETURN (1)
  12716.                             END
  12717.  
  12718.                         IF NOT EXISTS (SELECT *
  12719.                                          FROM sysobjects
  12720.                                         WHERE type = 'RF'
  12721.                                           AND id = @filter)
  12722.  
  12723.                             BEGIN
  12724.                                 RAISERROR (14049, 16, -1)
  12725.                                 if @@trancount > 0
  12726.                                 begin
  12727.                                     ROLLBACK TRAN sp_changearticle
  12728.                                     commit tran
  12729.                                 end
  12730.                                 RETURN (1)
  12731.                             END
  12732.  
  12733.                     END
  12734.  
  12735.                 IF @value IS NULL SELECT @filter = 0
  12736.  
  12737.                 -----------------------------
  12738.                 -- save off the old filter
  12739.                 -----------------------------
  12740.  
  12741.                 SELECT @old_filter_name = object_name( filter )
  12742.                 FROM sysarticles WHERE artid = @artid
  12743.                 AND pubid = @pubid
  12744.  
  12745.                 IF @@ERROR <> 0 
  12746.                 BEGIN
  12747.                     if @@trancount > 0
  12748.                     begin
  12749.                         ROLLBACK TRAN sp_changearticle
  12750.                         commit tran
  12751.                     end
  12752.                     RETURN (1)
  12753.                 END
  12754.  
  12755.                 --------------------------------------------
  12756.                 -- Update the article with the new filter.
  12757.                 --------------------------------------------
  12758.  
  12759.                 UPDATE sysarticles
  12760.                    SET filter = @filter
  12761.                  WHERE artid = @artid
  12762.                    AND pubid = @pubid
  12763.  
  12764.                 IF @@ERROR <> 0 
  12765.                 BEGIN
  12766.                     if @@trancount > 0
  12767.                     begin
  12768.                         ROLLBACK TRAN sp_changearticle
  12769.                         commit tran
  12770.                     end
  12771.                     RETURN (1)
  12772.                 END
  12773.  
  12774.                 -- SQL SERVER > 7.x ONLY  disassociate old filter with table
  12775.                 -- and associate new one
  12776.  
  12777.                 IF ( 0 <> ( SELECT PATINDEX( '%[789].[0-9]%', @@version ) ) ) OR
  12778.                    ( 0 <> ( SELECT PATINDEX( '%[1-9][0-9].[0-9]%', @@version ) ) )   
  12779.                 BEGIN
  12780.  
  12781.                     ------------------------------------------
  12782.                     -- disassociate table from old filter proc
  12783.                     ------------------------------------------
  12784.  
  12785.                     EXEC dbo.sp_MSsetfilterparent @old_filter_name, 0
  12786.  
  12787.                     IF @@ERROR <> 0
  12788.                     BEGIN
  12789.                         if @@trancount > 0
  12790.                         begin
  12791.                             ROLLBACK TRAN sp_changearticle
  12792.                             commit tran
  12793.                         end
  12794.                         RETURN (1)
  12795.                     END
  12796.  
  12797.                     ------------------------------------------------------
  12798.                     -- set the parent of the filter proc to this object_id
  12799.                     ------------------------------------------------------
  12800.  
  12801.                     EXEC dbo.sp_MSsetfilterparent @value, @objid
  12802.  
  12803.                     IF @@ERROR <> 0
  12804.                     BEGIN
  12805.                         if @@trancount > 0
  12806.                         begin
  12807.                             ROLLBACK TRAN sp_changearticle
  12808.                             commit tran
  12809.                         end
  12810.                         RETURN (1)
  12811.                     END
  12812.                 END
  12813.  
  12814.             END
  12815.  
  12816.         IF LOWER(@property) = 'pre_creation_cmd'
  12817.             BEGIN
  12818.  
  12819.                 /*
  12820.                 ** Check to make sure that we have a valid pre_creation_cmd.
  12821.                 */
  12822.             IF @objtype = 'P' and LOWER(@value) NOT IN ('none', 'drop')
  12823.                 BEGIN
  12824.                     RAISERROR ( 14111, 16, -1 )
  12825.                     if @@trancount > 0
  12826.                     begin   
  12827.                         ROLLBACK TRAN sp_changearticle
  12828.                         commit tran
  12829.                     end
  12830.                     RETURN (1)
  12831.                 END
  12832.  
  12833.                 IF LOWER(@value) NOT IN ('none', 'drop', 'delete', 'truncate')
  12834.                     BEGIN
  12835.                         RAISERROR (14061, 16, -1)
  12836.                         if @@trancount > 0
  12837.                         begin
  12838.                             ROLLBACK TRAN sp_changearticle
  12839.                             commit tran
  12840.                         end
  12841.                         RETURN (1)
  12842.                     END
  12843.  
  12844.                 /*
  12845.                 ** Determine the integer value for the type.
  12846.                 */
  12847.  
  12848.                 IF LOWER(@value) = 'none'
  12849.                     SELECT @precmdid = 0
  12850.                 ELSE IF LOWER(@value) = 'drop'
  12851.                     SELECT @precmdid = 1
  12852.                 ELSE IF LOWER(@value) = 'delete'
  12853.                     SELECT @precmdid = 2
  12854.                 ELSE IF LOWER(@value) = 'truncate'
  12855.                     SELECT @precmdid = 3
  12856.  
  12857.                 /*
  12858.                 ** Update the article with the new pre_creation_cmd.
  12859.                 */
  12860.                 UPDATE sysarticles
  12861.                    SET pre_creation_cmd = @precmdid
  12862.                  WHERE artid = @artid
  12863.                    AND pubid = @pubid
  12864.  
  12865.                 IF @@ERROR <> 0 
  12866.                     BEGIN
  12867.                         if @@trancount > 0
  12868.                         begin
  12869.                             ROLLBACK TRAN sp_changearticle
  12870.                             commit tran
  12871.                         end
  12872.                         RETURN (1)
  12873.                     END
  12874.  
  12875.             END
  12876.  
  12877.         IF LOWER(@property) = 'status'
  12878.             BEGIN
  12879.                 /*
  12880.                 ** Determine the integer value for the type.
  12881.                 */
  12882.                 IF LOWER(@value) = 'not owner qualified'
  12883.                     UPDATE sysarticles 
  12884.                     SET status = status & ~4
  12885.                     WHERE artid = @artid
  12886.                                   AND pubid = @pubid
  12887.  
  12888.                 ELSE IF LOWER(@value) = 'owner qualified'
  12889.                     UPDATE sysarticles 
  12890.                     SET status = status | 4
  12891.                     WHERE artid = @artid
  12892.                                   AND pubid = @pubid
  12893.                      
  12894.                 ELSE IF LOWER(@value) = 'no column names'
  12895.                     UPDATE sysarticles 
  12896.                     SET status = status & ~8
  12897.                     WHERE artid = @artid
  12898.                                   AND pubid = @pubid
  12899.                      
  12900.                 ELSE IF LOWER(@value) = 'include column names'
  12901.                     UPDATE sysarticles 
  12902.                     SET status = status | 8
  12903.                     WHERE artid = @artid
  12904.                                   AND pubid = @pubid
  12905.  
  12906.                 ELSE IF LOWER(@value) = 'string literals'
  12907.                     UPDATE sysarticles 
  12908.                     SET status = status & ~16
  12909.                     WHERE artid = @artid
  12910.                                   AND pubid = @pubid
  12911.                      
  12912.                 ELSE IF LOWER(@value) = 'parameters'
  12913.                     UPDATE sysarticles 
  12914.                     SET status = status | 16
  12915.                     WHERE artid = @artid
  12916.                                   AND pubid = @pubid
  12917.                 ELSE IF LOWER(@value) = @dts_part
  12918.                 begin
  12919.                     if exists (select * from sysarticles where
  12920.                         artid = @artid and
  12921.                         status & 64 = 0)
  12922.                     begin
  12923.                         UPDATE sysarticles 
  12924.                             SET status = status | 64,
  12925.                                 upd_cmd = N'XCALL sp_MSXpd_' + @article
  12926.                             WHERE artid = @artid
  12927.                     end
  12928.                 end
  12929.                 ELSE IF LOWER(@value) = @no_dts_part
  12930.                 begin
  12931.                     if exists (select * from sysarticles where
  12932.                         artid = @artid and
  12933.                         status & 64 <> 0)
  12934.                     begin
  12935.                         UPDATE sysarticles 
  12936.                             SET status = status & ~64,
  12937.                                 upd_cmd = N'CALL sp_MSupd_' + @article
  12938.                             WHERE artid = @artid
  12939.                     end
  12940.                 end
  12941.                 IF @@ERROR <> 0 
  12942.                     BEGIN
  12943.                         if @@trancount > 0
  12944.                         begin
  12945.                             ROLLBACK TRAN sp_changearticle
  12946.                             commit tran
  12947.                         end
  12948.                         RETURN (1)
  12949.                     END
  12950.             END
  12951.  
  12952.         IF LOWER(@property) = 'schema_option'
  12953.             BEGIN
  12954.                 IF @value IS NULL
  12955.                     BEGIN
  12956.                         RAISERROR(14146, 16,1)
  12957.                         if @@trancount > 0
  12958.                         begin
  12959.                             ROLLBACK TRAN sp_changearticle
  12960.                             commit tran
  12961.                         end
  12962.                         RETURN (1)
  12963.                     END
  12964.  
  12965.                 CREATE TABLE #tab_changearticle (value varbinary(8) NULL)
  12966.                                      
  12967.                 IF @@ERROR <> 0 
  12968.                     BEGIN
  12969.                         if @@trancount > 0
  12970.                         begin
  12971.                             ROLLBACK TRAN sp_changearticle
  12972.                             commit tran
  12973.                         end
  12974.                         RETURN (1)
  12975.                     END
  12976.  
  12977.                 EXEC ('insert #tab_changearticle values (' + 
  12978.                         @value +')' )
  12979.                                      
  12980.                 IF @@ERROR <> 0 
  12981.                     BEGIN
  12982.                         if @@trancount > 0
  12983.                         begin
  12984.                             ROLLBACK TRAN sp_changearticle
  12985.                             commit tran
  12986.                         end
  12987.                         RETURN (1)
  12988.                     END
  12989.                 
  12990.                 IF @objtype = 'P' AND EXISTS (SELECT * from #tab_changearticle 
  12991.                     WHERE value <> 0x0000000000000000 AND
  12992.                           value <> 0x0000000000000001 )
  12993.                     BEGIN
  12994.                         RAISERROR ( 20014, 16, -1 )
  12995.                         if @@trancount > 0
  12996.                         begin
  12997.                             ROLLBACK TRAN sp_changearticle
  12998.                             commit tran
  12999.                         end
  13000.                         RETURN (1)
  13001.                     END
  13002.  
  13003.                 --
  13004.                 -- For queued updating publications
  13005.                 -- DRI option has to be included
  13006.                 --
  13007.                 if ((@allow_queued_tran = 1) and 
  13008.                     exists (select * from #tab_changearticle where 
  13009.                         fn_replgetbinary8lodword(fn_replprepadbinary8(value)) & 0x8000 = 0))
  13010.                 BEGIN
  13011.                     RAISERROR (21394, 16, 2)
  13012.                     if @@trancount > 0
  13013.                     begin
  13014.                         ROLLBACK TRAN sp_changearticle
  13015.                         commit tran
  13016.                     end
  13017.                     RETURN (1)
  13018.                 END
  13019.  
  13020.                 -- Seems to be a good place to check and see if using 
  13021.                 -- collation 0x00001000 or extended property 0x00002000
  13022.                 declare @schema_option_int int
  13023.                 select @schema_option_int  = 
  13024.                     fn_replgetbinary8lodword(fn_replprepadbinary8(value)) 
  13025.                 from #tab_changearticle
  13026.                 if ((@schema_option_int & 0x000001000 <> 0) or 
  13027.                     (@schema_option_int & 0x000002000 <> 0))
  13028.                 select @backward_comp_level = 40
  13029.                 -- End 
  13030.                
  13031.                 UPDATE sysarticles 
  13032.                    SET schema_option = fn_replprepadbinary8(tab.value) 
  13033.                   FROM #tab_changearticle tab 
  13034.                  WHERE artid = @artid
  13035.                    AND pubid = @pubid
  13036.                 DROP TABLE #tab_changearticle 
  13037.                                      
  13038.                 IF @@ERROR <> 0 
  13039.                     BEGIN
  13040.                         if @@trancount > 0
  13041.                         begin
  13042.                             ROLLBACK TRAN sp_changearticle
  13043.                             commit tran
  13044.                         end
  13045.                         RETURN (1)
  13046.                     END
  13047.  
  13048.             END
  13049.  
  13050.         IF LOWER(@property) = 'destination_owner'
  13051.             BEGIN
  13052.                 IF @value IS NOT NULL
  13053.                 BEGIN
  13054.                     EXECUTE @retcode = dbo.sp_validname @value
  13055.  
  13056.                     IF @retcode <> 0
  13057.                     BEGIN
  13058.                         if @@trancount > 0
  13059.                         begin
  13060.                             ROLLBACK TRAN sp_changearticle
  13061.                             commit tran
  13062.                         end
  13063.                         RETURN (1)
  13064.                     END
  13065.                 END
  13066.  
  13067.                 UPDATE sysarticles SET dest_owner = @value from 
  13068.                     sysarticles WHERE artid = @artid
  13069.                                   AND pubid = @pubid
  13070.                                      
  13071.                 IF @@ERROR <> 0 
  13072.                     BEGIN
  13073.                         if @@trancount > 0
  13074.                         begin
  13075.                             ROLLBACK TRAN sp_changearticle
  13076.                             commit tran
  13077.                         end
  13078.                         RETURN (1)
  13079.                     END
  13080.  
  13081.             END
  13082.  
  13083.            
  13084.         if  LOWER(@property) = 'pub_identity_range'
  13085.         begin
  13086.             if not exists (select * from sysarticleupdates where artid = @artid and
  13087.                 identity_support = 1)
  13088.             begin
  13089.                 raiserror(21235, 16, -1, @property)
  13090.                 goto UNDO
  13091.             end
  13092.  
  13093.             declare @pub_range bigint
  13094.             select @pub_range = convert(bigint, @value) 
  13095.             if @pub_range < 0
  13096.             begin
  13097.                 raiserror(21232, 16, -1)
  13098.                 goto UNDO
  13099.             end
  13100.  
  13101.             if exists (select * from MSpub_identity_range where objid = @objid and
  13102.                 pub_range < 0)
  13103.                 select @pub_range = @pub_range * -1
  13104.             
  13105.             update MSpub_identity_range set
  13106.                 pub_range = @pub_range 
  13107.                 where objid=@objid
  13108.             if @@error < 0
  13109.                 goto UNDO
  13110.         end
  13111.                 
  13112.         if  LOWER(@property) = 'identity_range'
  13113.         begin
  13114.             if not exists (select * from sysarticleupdates where artid = @artid and
  13115.                 identity_support = 1)
  13116.             begin
  13117.                 raiserror(21235, 16, -1, @property)
  13118.                 goto UNDO
  13119.             end
  13120.  
  13121.             declare @range bigint
  13122.             select @range = convert(bigint, @value) 
  13123.             if @range < 0
  13124.             begin
  13125.                 raiserror(21232, 16, -1)
  13126.                 goto UNDO
  13127.             end
  13128.  
  13129.             if exists (select * from MSpub_identity_range where objid = @objid and
  13130.                 range < 0)
  13131.                 select @range = @range * -1
  13132.             
  13133.             update MSpub_identity_range set
  13134.                 range = @range 
  13135.                 where objid=@objid
  13136.             if @@error < 0
  13137.                 goto UNDO
  13138.  
  13139.             -- Distributor side data will be changed later by sp_MSchange_article.
  13140.         end
  13141.  
  13142.         -- Check to see if the range is too big.
  13143.         -- Must be down after the change. If the check fails, the transaction
  13144.         -- will be rolled back.
  13145.         if  LOWER(@property) in ('pub_identity_range', 'identity_range')
  13146.         begin
  13147.             declare @pub_identity_range bigint, @identity_range int
  13148.             select @pub_identity_range = pub_range, 
  13149.                 @identity_range = range from MSpub_identity_range where
  13150.                 objid = @objid 
  13151.  
  13152.             declare @xtype int, @xprec int, @max_range bigint
  13153.             select @xtype=xtype, @xprec=xprec from syscolumns where id=@objid and 
  13154.                 columnproperty(id, name, 'IsIdentity')=1
  13155.             select @max_range =
  13156.                     case @xtype when 52 then power((convert(bigint,2)), 8*2-1) - 1 --smallint 
  13157.                         when 48 then power((convert(bigint,2)), 8-1) - 1          --tinyint
  13158.                         when 56 then power((convert(bigint,2)), 8*4-1) - 1          --int
  13159.                         when 127 then power((convert(bigint,2)), 62) - 1 + power((convert(bigint,2)), 62)      --bigint
  13160.                            when 108 then power((convert(bigint,10)), @xprec)      --numeric
  13161.                            when 106 then power((convert(bigint,10)), @xprec)      --decimal
  13162.                      else
  13163.                         power((convert(bigint,2)), 62) + power((convert(bigint,2)), 62) - 1  -- defaulted to bigint
  13164.                     end
  13165.         
  13166.             declare @source_table nvarchar (386)
  13167.             exec @retcode = dbo.sp_MSget_qualified_name @objid, @source_table output
  13168.             if @retcode <> 0 or @@error <> 0
  13169.                 goto UNDO
  13170.             if @pub_identity_range * 2 + @identity_range > (@max_range - IDENT_CURRENT(@source_table))
  13171.                 begin
  13172.                     raiserror(21290, 16, -1)
  13173.                     goto UNDO
  13174.                 end
  13175.         end
  13176.  
  13177.         if  LOWER(@property) = 'threshold'
  13178.         begin
  13179.             if not exists (select * from sysarticleupdates where artid = @artid and
  13180.                 identity_support = 1)
  13181.             begin
  13182.                 raiserror(21235, 16, -1, @property)
  13183.                 goto UNDO
  13184.             end
  13185.  
  13186.             declare @threshold bigint
  13187.             select @threshold = convert(int, @value) 
  13188.             if @threshold < 1 or @threshold > 100
  13189.             begin
  13190.                 raiserror(21233, 16, -1)
  13191.                 goto UNDO
  13192.             end
  13193.  
  13194.             update MSpub_identity_range set
  13195.                 threshold = @threshold
  13196.                 where objid=@objid
  13197.             if @@error < 0
  13198.                 goto UNDO
  13199.             -- Distributor side data will be changed later by sp_MSchange_article.
  13200.         end
  13201.  
  13202.         -------------------------------------------------------------------------
  13203.         -- some info on articles is also stored at the distributor.
  13204.         -- update info at distributor if these properties change
  13205.         -------------------------------------------------------------------------
  13206.  
  13207.         if LOWER(@property) in ( N'description', N'dest_table', N'dest_object', 
  13208.             'identity_range', 'threshold' )
  13209.         BEGIN
  13210.             /*
  13211.             ** Get distribution server information for remote RPC call.
  13212.             */
  13213.             EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  13214.                @distribdb   = @distribdb OUTPUT
  13215.             IF @@ERROR <> 0 or @retcode <> 0
  13216.             BEGIN
  13217.                 RAISERROR (14071, 16, -1)
  13218.                 if @@trancount > 0
  13219.                 begin
  13220.                     ROLLBACK TRAN sp_changearticle
  13221.                     commit tran
  13222.                 end
  13223.                 RETURN (1)
  13224.             END
  13225.  
  13226.             SELECT @dbname =  DB_NAME()
  13227.  
  13228.             SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  13229.                 '.dbo.sp_MSchange_article'
  13230.             EXECUTE @retcode = @distproc
  13231.                 @publisher = @@SERVERNAME,
  13232.                 @publisher_db = @dbname,
  13233.                 @publication = @publication,
  13234.                 @article = @article,
  13235.                 @article_id = @artid,
  13236.                 @property = @property,
  13237.                 @value = @value
  13238.  
  13239.  
  13240.             IF @@ERROR <> 0 OR @retcode <> 0
  13241.             BEGIN
  13242.                 if @@trancount > 0
  13243.                 begin
  13244.                     ROLLBACK TRAN sp_changearticle
  13245.                     commit tran
  13246.                 end
  13247.                 RETURN (1)
  13248.             END
  13249.         END
  13250.  
  13251.         -- Have to call this stored procedure to invalidate existing snapshot or reint
  13252.         -- subscriptions if needed
  13253.         EXECUTE @retcode  = dbo.sp_MSreinit_article
  13254.             @publication = @publication, 
  13255.             @article = @article,
  13256.             @need_new_snapshot = @need_new_snapshot,
  13257.             @need_reinit_subscription = @need_reinit_subscription
  13258.             ,@force_invalidate_snapshot = @force_invalidate_snapshot    /* Force invalidate existing snapshot */
  13259.             ,@force_reinit_subscription = @force_reinit_subscription    /* Force reinit subscription */
  13260.         IF @@ERROR <> 0 OR @retcode <> 0
  13261.             GOTO UNDO
  13262.  
  13263.  
  13264. if @backward_comp_level > 10
  13265.     update syspublications set backward_comp_level = @backward_comp_level where pubid = @pubid
  13266.     COMMIT TRAN
  13267.  
  13268.     /*
  13269.     ** Force the article cache to be refreshed with the new definition.
  13270.     */
  13271.     EXECUTE dbo.sp_replflush
  13272.  
  13273.     /*
  13274.     ** Return succeed.
  13275.     */
  13276.  
  13277.     RAISERROR (14025, 10, -1)
  13278.     RETURN (0)
  13279.  
  13280. UNDO:
  13281.     if @@TRANCOUNT > 0
  13282.     begin
  13283.         ROLLBACK TRAN sp_changearticle
  13284.         COMMIT TRAN
  13285.     end
  13286.     return(1)
  13287. END
  13288. go
  13289.  
  13290. dump tran master with no_log
  13291. go
  13292.  
  13293. EXEC dbo.sp_MS_marksystemobject sp_changearticle
  13294. GO
  13295.  
  13296. print ''
  13297. print 'Creating procedure sp_droparticle'
  13298. go
  13299.  
  13300. CREATE PROCEDURE sp_droparticle(
  13301.     @publication sysname,     /* The publication name */
  13302.     @article sysname,          /* The article name */
  13303.     @ignore_distributor bit = 0,    
  13304.     @force_invalidate_snapshot bit = 0    /* Force invalidate existing snapshot */
  13305.  
  13306. AS
  13307. BEGIN
  13308.     /*
  13309.     ** Declarations.
  13310.     */
  13311.  
  13312.     DECLARE @cmd nvarchar(255)
  13313.     DECLARE @objid int
  13314.     DECLARE @pubid int
  13315.     DECLARE @publish_bit smallint
  13316.     DECLARE @retcode int
  13317.     DECLARE @filter_name sysname
  13318.     DECLARE @view_name sysname
  13319.     DECLARE @type tinyint
  13320.     DECLARE @procnum smallint
  13321.     DECLARE @virtual_id smallint
  13322.     DECLARE @push tinyint
  13323.     DECLARE @distributor sysname
  13324.     DECLARE @distribdb sysname
  13325.     DECLARE @distproc nvarchar (255)
  13326.     DECLARE @dbname sysname
  13327.     -- SyncTran
  13328.     DECLARE @allow_sync_tran_id bit
  13329.     DECLARE @allow_queued_tran_id bit
  13330.     declare @artid int, @insproc_id int, @updproc_id int, @delproc_id int, @updtrig_id int
  13331.     declare @filter_id int
  13332.     declare @view_id int
  13333.     declare @tran_conflict_tabid int
  13334.     declare @tran_conflict_procid int
  13335.  
  13336.     SET NOCOUNT ON
  13337.  
  13338.     /*
  13339.     ** Initializations.
  13340.     */
  13341.  
  13342.     SELECT @virtual_id = -1     /* Const: virtual subscriber id */
  13343.     SELECT @publish_bit = 1
  13344.  
  13345.  
  13346.     /*
  13347.     ** Security Check.
  13348.     */
  13349.     exec @retcode = dbo.sp_MSreplcheck_publish
  13350.     if @@ERROR <> 0 or @retcode <> 0
  13351.         return(1)
  13352.  
  13353.     /*
  13354.     ** Parameter Check: @publication.
  13355.     ** The @publication name must conform to the rules for identifiers.
  13356.     */
  13357.  
  13358.     IF @publication IS NULL
  13359.         BEGIN
  13360.             RAISERROR (14043, 16, -1, '@publication')
  13361.             RETURN (1)
  13362.         END
  13363.  
  13364.     EXECUTE @retcode = dbo.sp_validname @publication
  13365.  
  13366.     IF @retcode <> 0
  13367.     RETURN (1)
  13368.  
  13369.     IF NOT EXISTS (SELECT * FROM syspublications WHERE name = @publication)
  13370.         BEGIN
  13371.             RAISERROR (20026, 11, -1, @publication)
  13372.             RETURN (1)
  13373.         END
  13374.  
  13375.  
  13376.     /*
  13377.     ** Get the @pubid.
  13378.     */
  13379.  
  13380.     -- SyncTran
  13381.     --SELECT @pubid = pubid FROM syspublications WHERE name = @publication
  13382.     SELECT @pubid = pubid, @allow_sync_tran_id = allow_sync_tran,
  13383.         @allow_queued_tran_id = allow_queued_tran
  13384.     FROM syspublications WHERE name = @publication
  13385.  
  13386.     /*
  13387.     ** Parameter Check:  @article.
  13388.     ** If the @article is 'all', drop all articles for the specified
  13389.     ** publication (@publication).
  13390.     */
  13391.  
  13392.     IF LOWER(@article) = 'all'
  13393.         BEGIN
  13394.             -- If drop all articles, set force flag to true
  13395.             select @force_invalidate_snapshot = 1
  13396.             DECLARE hC  CURSOR LOCAL FAST_FORWARD FOR 
  13397.                 SELECT DISTINCT  name FROM sysextendedarticlesview 
  13398.                     WHERE pubid = @pubid
  13399.             OPEN hC
  13400.             FETCH hC INTO @article
  13401.             WHILE (@@fetch_status <> -1)
  13402.                 BEGIN
  13403.                     EXECUTE dbo.sp_droparticle 
  13404.                         @publication = @publication, 
  13405.                         @article = @article,
  13406.                         @ignore_distributor = @ignore_distributor,
  13407.                         @force_invalidate_snapshot = @force_invalidate_snapshot
  13408.  
  13409.                     FETCH hC INTO @article
  13410.                 END
  13411.             CLOSE hC
  13412.             DEALLOCATE hC
  13413.             RETURN (0)
  13414.         END
  13415.  
  13416.     /*
  13417.     ** Parameter Check: @article.
  13418.     ** The @article name must conform to the rules for identifiers.
  13419.     */
  13420.  
  13421.     IF @article IS NULL
  13422.         BEGIN
  13423.             RAISERROR (14043, 16, -1, '@article')
  13424.             RETURN (1)
  13425.         END
  13426.  
  13427.     /*
  13428.     EXECUTE @retcode = dbo.sp_validname @article
  13429.  
  13430.     IF @retcode <> 0
  13431.     RETURN (1)
  13432.     */
  13433.  
  13434.     /*
  13435.     ** Ascertain the existence of the article.
  13436.     */
  13437.  
  13438.     IF NOT EXISTS (SELECT *
  13439.                      FROM sysextendedarticlesview
  13440.                     WHERE name = @article
  13441.                       AND pubid = @pubid)
  13442.         BEGIN
  13443.             RAISERROR (20027, 11, -1, @article)
  13444.         RETURN (1)
  13445.         END
  13446.  
  13447.     /*
  13448.     ** Check to make sure that there are no 'real' subscriptions on the article.
  13449.     */
  13450.  
  13451.     IF EXISTS (SELECT *
  13452.                  FROM syssubscriptions, sysextendedarticlesview
  13453.                 WHERE sysextendedarticlesview.name = @article
  13454.                   AND sysextendedarticlesview.pubid = @pubid
  13455.                   AND sysextendedarticlesview.artid = syssubscriptions.artid
  13456.                   AND syssubscriptions.srvid <> @virtual_id)
  13457.         BEGIN
  13458.             RAISERROR (14046, 16, -1)
  13459.             RETURN (1)
  13460.         END
  13461.  
  13462.     -- 
  13463.     -- If SyncTran/QueuedTran enabled
  13464.     -- retrieve info from sysarticle updates
  13465.     --
  13466.     if (@allow_sync_tran_id = 1 or @allow_queued_tran_id = 1)
  13467.     begin
  13468.         select @artid = artid from sysarticles where name = @article and pubid = @pubid
  13469.         select @insproc_id = sync_ins_proc, @updproc_id = sync_upd_proc, @delproc_id = sync_del_proc,
  13470.             @updtrig_id = sync_upd_trig,
  13471.             @tran_conflict_tabid = conflict_tableid,
  13472.             @tran_conflict_procid = ins_conflict_proc
  13473.         from sysarticleupdates
  13474.         where artid = @artid and pubid = @pubid 
  13475.     end
  13476.     -- end SyncTran
  13477.  
  13478.     /*
  13479.     ** Retrieve the object id of the underlying object,
  13480.     ** article id, and article type. Note that the 
  13481.     ** subsequent code relies on the values of the variables in
  13482.     ** the select list. Please do not remove any variable from 
  13483.     ** the seletc list unless you make sure that all the subsequent
  13484.     ** references to the variable are accounted for.  
  13485.     */
  13486.  
  13487.     SELECT @artid = artid, @objid = objid, @type = type
  13488.       FROM sysextendedarticlesview
  13489.      WHERE name = @article
  13490.        AND pubid = @pubid
  13491.  
  13492.     begin tran
  13493.     save TRAN droparticle
  13494.  
  13495.         -- @ignore_distributor is set to 1 when removing replication forcefully. In that
  13496.         -- case, no need to check or reinit
  13497.         if @ignore_distributor = 0
  13498.         begin
  13499.             -- Have to call this stored procedure to invalidate existing snapshot
  13500.             -- if there are any. immediate_sync_ready bit would be changed or error will be railsed.
  13501.             EXECUTE @retcode  = dbo.sp_MSreinit_article
  13502.                 @publication = @publication, 
  13503.                 @need_new_snapshot = 1,
  13504.                 @force_invalidate_snapshot = @force_invalidate_snapshot
  13505.             IF @@ERROR <> 0 OR @retcode <> 0
  13506.                 GOTO UNDO
  13507.         end
  13508.  
  13509.         /* Drop virtual subscription first for @immediate_sync publications
  13510.          */
  13511.         if EXISTS (SELECT * FROM syspublications WHERE
  13512.             name = @publication    AND
  13513.             immediate_sync = 1)
  13514.         BEGIN
  13515.             EXECUTE @retcode  = dbo.sp_dropsubscription 
  13516.                 @publication = @publication, 
  13517.                 @article = @article,
  13518.                 @subscriber = NULL,
  13519.                 @ignore_distributor = @ignore_distributor,
  13520.                 @reserved = 'internal'
  13521.             IF @@ERROR <> 0 OR @retcode <> 0
  13522.             BEGIN
  13523.                 if @@trancount > 0
  13524.                 begin
  13525.                     ROLLBACK TRAN droparticle
  13526.                     commit tran
  13527.                 end
  13528.                 RETURN (1)
  13529.             END
  13530.         END
  13531.  
  13532.         /* Drop article at the distributor side */
  13533.         /*
  13534.         ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
  13535.         */
  13536.         if @ignore_distributor = 0
  13537.         begin
  13538.  
  13539.             /*
  13540.             ** Get distribution server information for remote RPC call.
  13541.             */
  13542.             EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  13543.                @distribdb   = @distribdb OUTPUT
  13544.             IF @@ERROR <> 0 or @retcode <> 0
  13545.                 BEGIN
  13546.                     RETURN (1)
  13547.                 END
  13548.  
  13549.             SELECT @dbname =  DB_NAME()
  13550.         
  13551.             SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  13552.                 '.dbo.sp_MSdrop_article'
  13553.             EXECUTE @retcode = @distproc
  13554.                 @publisher = @@SERVERNAME,
  13555.                 @publisher_db = @dbname,
  13556.                 @publication = @publication,
  13557.                 @article = @article
  13558.  
  13559.             IF @@ERROR <> 0 OR @retcode <> 0
  13560.             BEGIN
  13561.                 if @@trancount > 0
  13562.                     ROLLBACK TRAN 
  13563.                 RETURN (1)
  13564.             END
  13565.         end
  13566.  
  13567.         IF @type IN (0x20, 0x40, 0x80)
  13568.         BEGIN
  13569.             -- Handle the schema only articles a little bit differently from 
  13570.             -- other articles as they are simpler objects. 
  13571.  
  13572.             -- Note that we have already obtained the article id earlier 
  13573.             -- so we can use that to delete the corresponding record
  13574.             -- in sysschemaarticles
  13575.             
  13576.             DELETE sysschemaarticles WHERE artid = @artid and pubid = @pubid
  13577.  
  13578.             -- If the object is no longer published as an schema only
  13579.             -- article, unmark its published for schema only bit (512) in 
  13580.             -- sysobjects/replinfo so that it can be dropped by the user.
  13581.             -- Note that we need to check sysmergeschemaarticles too.
  13582.  
  13583.  
  13584.             -- Note that we have obtained the object id for the undelying 
  13585.             -- object of this article already.
  13586.  
  13587.             IF NOT EXISTS (SELECT * 
  13588.                              FROM sysschemaarticles 
  13589.                             WHERE objid = @objid)
  13590.             BEGIN
  13591.                 SELECT @publish_bit = 512
  13592.                 IF NOT EXISTS (SELECT * 
  13593.                                  FROM sysobjects 
  13594.                                 WHERE name = 'sysmergeschemaarticles')
  13595.                 BEGIN
  13596.                     UPDATE sysobjects 
  13597.                        SET replinfo = replinfo & ~@publish_bit
  13598.                     WHERE id = @objid 
  13599.                 END
  13600.                 ELSE IF NOT EXISTS (SELECT * 
  13601.                                       FROM sysmergeschemaarticles
  13602.                                      WHERE objid = @objid)
  13603.                 BEGIN
  13604.                     UPDATE sysobjects 
  13605.                        SET replinfo = replinfo & ~@publish_bit
  13606.                     WHERE id = @objid 
  13607.                 END
  13608.             END  
  13609.         END
  13610.         ELSE
  13611.         BEGIN
  13612.         
  13613.             /*
  13614.             **  Delete article from sysarticles and clear publish bit in
  13615.             **  sysobjects.
  13616.             */
  13617.  
  13618.  
  13619.             /*
  13620.             ** If this article is the only one that references this object,
  13621.             ** then we can safely turn off the publish bit in sysobjects.
  13622.             */
  13623.  
  13624.             IF NOT EXISTS (SELECT *
  13625.                              FROM sysarticles
  13626.                             WHERE objid = @objid
  13627.                               AND NOT (name = @article AND pubid = @pubid))
  13628.                 BEGIN
  13629.  
  13630.                 UPDATE sysobjects SET replinfo = replinfo & ~ @publish_bit 
  13631.                     WHERE id = (SELECT objid FROM sysarticles WHERE name = @article 
  13632.                         AND pubid =  @pubid) 
  13633.  
  13634.                 /*
  13635.                 EXEC (@cmd)
  13636.  
  13637.                 IF @@ERROR <> 0
  13638.                     BEGIN
  13639.                         if @@trancount > 0
  13640.                             ROLLBACK TRAN
  13641.                         RAISERROR (14047, 16, -1, @article)
  13642.                         RETURN (1)
  13643.                     END
  13644.                 */
  13645.  
  13646.                 END
  13647.  
  13648.             /*
  13649.             ** Drop article view if not logbased manualview (type = 5)
  13650.             */
  13651.             IF (@type & 5) = 1
  13652.             BEGIN    
  13653.                 SELECT @view_id = sysobjects.id
  13654.                   FROM sysarticles, sysobjects
  13655.                  WHERE sysarticles.name = @article
  13656.                    AND pubid = @pubid
  13657.                    AND sync_objid = sysobjects.id
  13658.                    AND sysobjects.type = 'V'
  13659.                 exec sp_MSget_qualified_name @view_id, @view_name OUTPUT
  13660.  
  13661.             END
  13662.  
  13663.             /*
  13664.             ** Drop article filter if not logbased manualfilter (type = 3)
  13665.             */
  13666.             IF (@type & 3) = 1
  13667.             BEGIN    
  13668.                 SELECT @filter_id = sysobjects.id
  13669.                   FROM sysarticles, sysobjects
  13670.                  WHERE sysarticles.name = @article
  13671.                    AND pubid = @pubid
  13672.                    AND filter = sysobjects.id
  13673.                    AND sysobjects.type = 'RF'
  13674.  
  13675.                 exec sp_MSget_qualified_name @filter_id, @filter_name OUTPUT
  13676.        
  13677.             END
  13678.  
  13679.  
  13680.             IF( @type & 3 ) = 3
  13681.             BEGIN
  13682.                 select @filter_id =  filter from sysarticles
  13683.                 where name = @article and pubid = @pubid
  13684.  
  13685.                 exec sp_MSget_qualified_name @filter_id, @filter_name OUTPUT
  13686.  
  13687.                 if @filter_name is not null
  13688.                     EXEC dbo.sp_MSsetfilterparent @filter_name, 0
  13689.             
  13690.                 -- Clear base table dependency on the filter
  13691.                 EXEC dbo.sp_MSsetfilteredstatus @objid
  13692.  
  13693.                 -- This is a manual filter, we should not drop it automatically
  13694.                 -- since it is not created by us.
  13695.                 -- Set @filter_id to null so the object will not be dropped later.
  13696.                 select @filter_name = null
  13697.  
  13698.             END
  13699.  
  13700.  
  13701.             /*
  13702.             ** If this is a table based article, Drop all article columns.
  13703.             ** This is done to force all Text\Image column status to be updated.
  13704.             */
  13705.  
  13706.             IF (@type & 8) != 8
  13707.             BEGIN
  13708.  
  13709.                 -- propagate @ignore_distributor to sp_articlecolumn to allow forced cleanup
  13710.                 EXECUTE @retcode  = dbo.sp_articlecolumn @publication, @article,
  13711.                 @operation = 'drop', @ignore_distributor = @ignore_distributor
  13712.                 -- synctran
  13713.                 , @refresh_synctran_procs = 0
  13714.                 , @force_invalidate_snapshot = @force_invalidate_snapshot
  13715.                 IF @@ERROR <> 0 OR @retcode <> 0
  13716.                 BEGIN
  13717.                     if @@trancount > 0
  13718.                     begin
  13719.                         ROLLBACK TRAN droparticle
  13720.                         commit tran
  13721.                     end
  13722.                     RETURN (1)
  13723.                 END
  13724.             END
  13725.  
  13726.  
  13727.             /*
  13728.             ** Remove the row from sysarticles.
  13729.             */
  13730.             DELETE
  13731.               FROM sysarticles
  13732.              WHERE name = @article
  13733.                AND pubid = @pubid
  13734.  
  13735.             IF @@ERROR <> 0
  13736.             BEGIN
  13737.                 if @@trancount > 0
  13738.                     ROLLBACK TRAN 
  13739.                 RAISERROR (14047, 16, -1, @article)
  13740.                 RETURN (1)
  13741.             END
  13742.  
  13743.             -- SyncTran
  13744.             /*
  13745.             ** Drop associated sync tran procs and entries in sysarticle updates
  13746.             */
  13747.             if (@allow_sync_tran_id = 1 or @allow_queued_tran_id = 1)
  13748.             begin
  13749.                 exec @retcode = dbo.sp_MSdrop_object 
  13750.                     @object_id = @insproc_id
  13751.                 if @retcode <> 0 or @@error <> 0
  13752.                     goto UNDO
  13753.  
  13754.                 exec @retcode = dbo.sp_MSdrop_object 
  13755.                     @object_id = @updproc_id
  13756.                 if @retcode <> 0 or @@error <> 0
  13757.                     goto UNDO
  13758.  
  13759.                 exec @retcode = dbo.sp_MSdrop_object 
  13760.                     @object_id = @delproc_id
  13761.                 if @retcode <> 0 or @@error <> 0
  13762.                     goto UNDO
  13763.             
  13764.                 if @updtrig_id is not null
  13765.                 begin
  13766.                     exec @retcode = dbo.sp_MSdrop_object 
  13767.                         @object_id = @updtrig_id
  13768.                     if @retcode <> 0 or @@error <> 0
  13769.                         goto UNDO
  13770.                 end
  13771.  
  13772.                 -- drop conflict tables as necessary
  13773.                 if @tran_conflict_tabid is not null
  13774.                 begin
  13775.                     exec @retcode = dbo.sp_MSdrop_object 
  13776.                         @object_id = @tran_conflict_tabid
  13777.                     if @retcode <> 0 or @@error <> 0
  13778.                         goto UNDO
  13779.                 end
  13780.  
  13781.                 if @tran_conflict_procid is not null
  13782.                 begin
  13783.                     exec @retcode = dbo.sp_MSdrop_object 
  13784.                         @object_id = @tran_conflict_procid
  13785.                     if @retcode <> 0 or @@error <> 0
  13786.                         goto UNDO
  13787.                 end
  13788.  
  13789.                 delete from sysarticleupdates where artid = @artid and pubid = @pubid
  13790.                 if @@ERROR <> 0 
  13791.                 begin
  13792.                     if @@trancount > 0
  13793.                         ROLLBACK TRAN
  13794.                     RETURN (1)
  13795.  
  13796.                 end
  13797.  
  13798.                 -- Cleanup MSpub_identity_range if needed.
  13799.                 if not exists (select * from sysarticles where objid = @objid)
  13800.                 begin
  13801.                     if exists (select * from MSpub_identity_range where objid = @objid)
  13802.                     begin
  13803.                         -- Drop the identity range constraits.
  13804.                         -- RESEED and change constraint
  13805.                         exec @retcode = dbo.sp_MSreseed
  13806.                             @objid =  @objid,
  13807.                             -- next_seed and range can be anything.
  13808.                             @next_seed = 10,
  13809.                             @range = 10,
  13810.                             @is_publisher = -1,
  13811.                             @check_only = 1,
  13812.                             @drop_only = 1
  13813.                         IF @retcode <> 0 or @@ERROR <> 0 
  13814.                             GOTO UNDO
  13815.  
  13816.                         delete MSpub_identity_range where objid = @objid
  13817.                         if @@ERROR <> 0 
  13818.                             GOTO UNDO
  13819.                     end
  13820.                 end
  13821.             -- end SyncTran
  13822.             end
  13823.     end
  13824.     COMMIT TRAN
  13825.  
  13826.     IF @view_name IS NOT NULL
  13827.     BEGIN
  13828.         -- @view_name is already quoted.
  13829.         SELECT @cmd = 'drop view ' + @view_name
  13830.         exec (@cmd)
  13831.     END
  13832.  
  13833.     IF @filter_name IS NOT NULL
  13834.     BEGIN
  13835.         -- @filter_name is already quoted.
  13836.         SELECT @cmd = 'drop proc ' + @filter_name
  13837.         exec (@cmd)
  13838.     END
  13839.     /*
  13840.     ** Force the article cache to be refreshed; only if needed
  13841.     */
  13842.     if ( @ignore_distributor = 0 )
  13843.         EXECUTE dbo.sp_replflush
  13844.  
  13845.     return (0)
  13846.  
  13847. UNDO:
  13848.  
  13849.     if @@trancount > 0
  13850.     begin
  13851.         ROLLBACK TRANSACTION droparticle
  13852.         commit tran
  13853.     end
  13854.     RETURN (1)
  13855. END
  13856. go
  13857.  
  13858. EXEC dbo.sp_MS_marksystemobject sp_droparticle
  13859. GO
  13860.  
  13861. print ''
  13862. print 'Creating procedure sp_droppublication'
  13863. go
  13864.  
  13865. CREATE PROCEDURE sp_droppublication(
  13866.         @publication sysname,       /* The publication name */
  13867.         @ignore_distributor bit = 0
  13868.         ) AS
  13869.  
  13870.     /*
  13871.     ** Declarations.
  13872.     */
  13873.  
  13874.     DECLARE @article sysname
  13875.     DECLARE @cmd nvarchar(255)
  13876.     DECLARE @retcode int
  13877.     DECLARE @distributor sysname
  13878.     DECLARE @distribdb sysname
  13879.     DECLARE @distproc nvarchar (255)
  13880.     DECLARE @agentname nvarchar (40)
  13881.     DECLARE @dbname sysname
  13882.     DECLARE @virtual_id smallint
  13883.     DECLARE @ad_guidname sysname
  13884.     
  13885.     SELECT @virtual_id = -1
  13886.     select @dbname = db_name()
  13887.     select @ad_guidname = NULL
  13888.     /*
  13889.     ** Security check
  13890.     */
  13891.     exec @retcode = dbo.sp_MSreplcheck_publish
  13892.     if @@ERROR <> 0 or @retcode <> 0
  13893.         return(1)
  13894.  
  13895.     /*
  13896.     ** Parameter Check:  @publication.
  13897.     ** If the @publication is 'all', drop all publications.  Otherwise,
  13898.     ** make sure the @publication is a valid non-null identifier.
  13899.     ** Delete the logreader agent after all the publications have been 
  13900.     ** removed.
  13901.     */
  13902.  
  13903.     IF LOWER(@publication) = 'all'
  13904.         BEGIN
  13905.             DECLARE hC1  CURSOR LOCAL FAST_FORWARD FOR 
  13906.                 SELECT DISTINCT name FROM syspublications 
  13907.                     WHERE pubid NOT IN 
  13908.                         (SELECT pubid FROM sysextendedarticlesview WHERE artid IN 
  13909.                             (SELECT artid FROM syssubscriptions WHERE srvid <> @virtual_id))
  13910.             OPEN hC1
  13911.             FETCH hC1 INTO @publication
  13912.             WHILE (@@fetch_status <> -1)
  13913.                 BEGIN
  13914.                     EXECUTE dbo.sp_droppublication @publication,
  13915.                         @ignore_distributor = @ignore_distributor
  13916.                     FETCH hC1 INTO @publication
  13917.                 END
  13918.             CLOSE hC1
  13919.             DEALLOCATE hC1
  13920.             RETURN (0)
  13921.         END
  13922.  
  13923.     IF @publication IS NULL
  13924.         BEGIN
  13925.             RAISERROR (14003, 16, -1)
  13926.             RETURN (1)
  13927.         END
  13928.  
  13929.     EXECUTE @retcode = dbo.sp_validname @publication
  13930.  
  13931.     IF @retcode <> 0
  13932.     RETURN (1)
  13933.  
  13934.     /*
  13935.     ** Ascertain the existence of the publication and get the taskid.
  13936.     */
  13937.     IF NOT EXISTS (SELECT *
  13938.                      FROM syspublications
  13939.                     WHERE name = @publication)
  13940.     BEGIN
  13941.         RAISERROR (20026, 11, -1, @publication)
  13942.         RETURN (1)
  13943.     END
  13944.  
  13945.     /*
  13946.     ** Check to make sure that there are no subscriptions on the publication.
  13947.     */
  13948.  
  13949.     IF EXISTS (SELECT *
  13950.                  FROM syssubscriptions a, sysextendedarticlesview b, syspublications c
  13951.                 WHERE c.name = @publication
  13952.                   AND c.pubid = b.pubid
  13953.                   AND b.artid = a.artid
  13954.                   AND a.srvid <>@virtual_id)
  13955.         BEGIN
  13956.             RAISERROR (14005, 16, -1)
  13957.             RETURN (1)
  13958.         END
  13959.  
  13960.     /*
  13961.     ** Delete all articles from the publication.
  13962.     */
  13963.  
  13964.     EXECUTE dbo.sp_droparticle @publication = @publication, 
  13965.         @article = N'all',
  13966.         @ignore_distributor = @ignore_distributor
  13967.         , @force_invalidate_snapshot = 1
  13968.     IF @@ERROR <> 0 OR  @retcode <> 0
  13969.         RETURN (1)
  13970.  
  13971.     select @ad_guidname = ad_guidname from syspublications where name=@publication
  13972.  
  13973.     BEGIN TRAN
  13974.  
  13975.     /*
  13976.     ** Delete publication from syspublications.
  13977.     */
  13978.  
  13979.     DELETE FROM syspublications WHERE name = @publication
  13980.  
  13981.     IF @@ERROR <> 0
  13982.         GOTO UNDO
  13983.  
  13984.     /*
  13985.     ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
  13986.     */
  13987.     if @ignore_distributor = 0
  13988.     begin
  13989.  
  13990.         /*
  13991.         ** Get distribution server information for remote RPC call.
  13992.         */
  13993.  
  13994.         EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  13995.                                            @distribdb = @distribdb OUTPUT
  13996.  
  13997.         IF @@ERROR <> 0 OR  @retcode <> 0
  13998.             BEGIN
  13999.                 RAISERROR (14071, 16, -1)
  14000.                 RETURN (1)
  14001.             END
  14002.  
  14003.         /*
  14004.         ** Delete sync agent of Publication if it exists.
  14005.         */
  14006.         SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + '.dbo.sp_MSdrop_snapshot_agent'
  14007.         EXECUTE @retcode = @distproc 
  14008.             @publisher = @@SERVERNAME,
  14009.             @publisher_db = @dbname,
  14010.             @publication = @publication
  14011.  
  14012.         IF @@ERROR <> 0 or @retcode <> 0
  14013.             GOTO UNDO
  14014.  
  14015.         IF NOT EXISTS (SELECT * FROM syspublications  where repl_freq = 0)
  14016.             BEGIN
  14017.                 /*
  14018.                 ** Delete logreader agent, continue if drop is not successful
  14019.                 */
  14020.                 SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + '.dbo.sp_MSdrop_logreader_agent'
  14021.                 EXECUTE @retcode = @distproc @publisher = @@SERVERNAME,
  14022.                     @publisher_db = @dbname,
  14023.                     -- 'ALL' is used in sp_addpublication.
  14024.                     @publication = 'ALL'
  14025.                 IF @@ERROR <> 0 or @retcode <> 0
  14026.                     GOTO UNDO
  14027.             END
  14028.  
  14029.         /*
  14030.         ** Delete the publication at the distribution server
  14031.         */
  14032.         SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  14033.             '.dbo.sp_MSdrop_publication'
  14034.         EXECUTE @retcode = @distproc
  14035.             @publisher = @@SERVERNAME,
  14036.             @publisher_db = @dbname,
  14037.             @publication = @publication
  14038.         IF @@ERROR <> 0 or @retcode <> 0
  14039.             GOTO UNDO
  14040.     end
  14041.  
  14042.     DECLARE @retval  INT
  14043.     EXECUTE @retval = master.dbo.xp_MSADEnabled
  14044.     if @ad_guidname is not NULL 
  14045.     begin
  14046.         if @retval = 0
  14047.         begin
  14048.             exec @retcode=master.dbo.sp_ActiveDirectory_Obj 'DELETE', 'PUBLICATION', @publication, @dbname, @ad_guidname
  14049.             if @@ERROR<>0 or @retcode<>0
  14050.             begin
  14051.                 raiserror(21369, 16, -1, @publication)
  14052.                 goto UNDO
  14053.             end
  14054.         end
  14055.         else
  14056.         begin
  14057.             RAISERROR(21254, 16, -1, @publication)
  14058.             GOTO UNDO
  14059.         end
  14060.     end
  14061.  
  14062.     COMMIT TRAN
  14063.  
  14064.     -- Since we drop publisher_database_id in sp_MSdrop_publication at the distribution db when
  14065.     -- dropping the last tran (snapshot) publication, we should call repldone here to clear
  14066.     -- repl counters and lsns. This will ensure the correctness of repl counters and avoid
  14067.     -- unnecessary log scan in the logreader if it is created again after this.
  14068.     -- Ignore all errors.
  14069.     if not exists (select * from syspublications)
  14070.     begin
  14071.         DECLARE @replicate_bit    smallint
  14072.         SELECT @replicate_bit = 2
  14073.  
  14074.         -- Used for attach and restored db.
  14075.         -- sysservers table in master db might be changed so that
  14076.         -- sp_dropsubscription won't work, which left repl bits marked in
  14077.         -- sysobjects.
  14078.         -- We have to unmark them before calling sp_repldone, otherwise
  14079.         -- A new transaction updating those objects will be considered
  14080.         -- as repl tran. It will set the truncation point to not null, which will
  14081.         -- prevent log truncation.
  14082.         UPDATE sysobjects SET replinfo =  replinfo & ~@replicate_bit
  14083.  
  14084.         /* ensure we can get in as logreader */
  14085.         exec dbo.sp_replflush
  14086.  
  14087.         /* clear repl dbtable fields unmark all xacts marked for replication */
  14088.         exec dbo.sp_repldone NULL, NULL, 0, 0, 1
  14089.     
  14090.         /* release our hold on the db as logreader */
  14091.         EXEC dbo.sp_replflush
  14092.  
  14093.         -- Run checkpoint to make sp_repldone result durable (write repl dbtable fields
  14094.         -- into the checkpoint record).
  14095.         checkpoint
  14096.     end        
  14097.  
  14098.     return (0)  
  14099.     
  14100. UNDO:
  14101.     if @@TRANCOUNT = 1
  14102.         ROLLBACK TRAN
  14103.     else
  14104.         COMMIT TRAN
  14105.     return(1)
  14106. GO
  14107.  
  14108. EXEC dbo.sp_MS_marksystemobject sp_droppublication
  14109. GO
  14110.  
  14111. print ''
  14112. print 'Creating procedure sp_dropsubscription'
  14113. go
  14114. CREATE PROCEDURE sp_dropsubscription (
  14115.     @publication sysname = NULL,   /* The publication name */
  14116.     @article sysname = NULL,       /* The article name */
  14117.     @subscriber sysname,           /* The subscriber name */
  14118.     @destination_db sysname =NULL,                /* Name of the destination database */
  14119.                                         /* If null, all the subscriptions from that
  14120.                                             subscriber will be dropped */
  14121.     @ignore_distributor bit = 0,
  14122.  
  14123.     @reserved nvarchar(10) = NULL            /* reserved, used when calling from other system */
  14124.                                             /* stored procedures, it will be set to 'internal'.*/
  14125.                                             /* It should never be used directly */
  14126.     ) AS
  14127.  
  14128.     /*
  14129.     ** Declarations.
  14130.     */
  14131.  
  14132.     DECLARE @subscriber_bit smallint
  14133.     DECLARE @cmd nvarchar(255)
  14134.     DECLARE @srvid smallint
  14135.     DECLARE @artid int
  14136.     DECLARE @retcode int
  14137.     DECLARE @active tinyint
  14138.     DECLARE @internal nvarchar(10)
  14139.     DECLARE @expand_article nvarchar(10)
  14140.     DECLARE @push tinyint
  14141.     DECLARE @virtual_id smallint
  14142.     DECLARE @login_name sysname
  14143.     DECLARE @immediate_sync bit
  14144.     DECLARE @subscription_type int
  14145.     DECLARE @qualified_subscription_name nvarchar(512)
  14146.     DECLARE @sync_method tinyint
  14147.     DECLARE @concurrent tinyint
  14148.     DECLARE @concurrent_char tinyint
  14149.  
  14150.     /*
  14151.     ** Initializations.
  14152.     */
  14153.     SET NOCOUNT ON
  14154.     SELECT @subscriber_bit = 4  /* Const: subscription server status */
  14155.     SELECT @active = 2          /* Const: subscription status 'active' */
  14156.     SELECT @push = 0        /* Const: push publication type */
  14157.     SELECT @virtual_id = -1 /* Const: virtual subscriber id */
  14158.     SELECT @internal = 'internal' /* Const: Flag of calling internally from system */
  14159.                                   /* stored procedures     */
  14160.     SELECT @expand_article = 'expand_art' 
  14161.         /* Const: Flag of calling after expand 'all' for @article  */
  14162.     SELECT @concurrent = 3
  14163.     SELECT @concurrent_char = 4
  14164.  
  14165.     /* 
  14166.     ** Security Check.
  14167.     ** We use login_name stored in syssubscriptions to manage security 
  14168.     */
  14169.  
  14170.     -- Test distributor RPC connection before open the cursor
  14171.  
  14172.     /*
  14173.     ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
  14174.     */
  14175.     if @ignore_distributor = 0
  14176.     begin
  14177.         declare @distributor sysname
  14178.         EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT
  14179.         if @@ERROR <> 0 or @retcode <> 0
  14180.             return(1)
  14181.     end
  14182.  
  14183.     /*
  14184.     ** If the @subscriber is 'all', the user wants to cancel all subscriptions
  14185.     ** to the specified article(s).
  14186.     */
  14187.  
  14188.     IF LOWER(@subscriber) = 'all'
  14189.         BEGIN
  14190.             DECLARE hCdrop_subscription1  CURSOR LOCAL FAST_FORWARD FOR 
  14191.                 SELECT DISTINCT srvname 
  14192.                     FROM master..sysservers a, syssubscriptions b 
  14193.                     WHERE srvstatus & @subscriber_bit <> 0 
  14194.                     AND a.srvid = b.srvid
  14195.  
  14196.     -- With ANSI Defaults ON, the cursor will automatically
  14197.     -- be closed on commit.   Since this proc gets called recursively, 
  14198.     -- this can happen.  So check before opening. 
  14199.     IF CURSOR_STATUS('local','hCdrop_subscription1') = -1
  14200.             OPEN hCdrop_subscription1
  14201.  
  14202.             -- must owner qual proc invoke to exec inside server on restore/attach cleanup
  14203.             FETCH hCdrop_subscription1 INTO @subscriber
  14204.             WHILE (@@fetch_status <> -1)
  14205.                 BEGIN
  14206.                     EXECUTE dbo.sp_dropsubscription 
  14207.                         @publication = @publication,
  14208.                         @article = @article,
  14209.                         @subscriber  = @subscriber,
  14210.                         @destination_db = 'all',
  14211.                         @ignore_distributor = @ignore_distributor,
  14212.                         @reserved = @reserved
  14213.  
  14214.         IF CURSOR_STATUS('local','hCdrop_subscription1') = -1
  14215.                 OPEN hCdrop_subscription1
  14216.                 FETCH hCdrop_subscription1 INTO @subscriber
  14217.                 END
  14218.             CLOSE hCdrop_subscription1
  14219.             DEALLOCATE hCdrop_subscription1
  14220.             RETURN (0)
  14221.         END
  14222.  
  14223.     
  14224.     
  14225.     /*
  14226.     ** Parameter Check: @subscriber.
  14227.     **
  14228.     ** Check if the server exists and that it is a subscription server.
  14229.     **
  14230.     */
  14231.     IF @subscriber IS NULL
  14232.         BEGIN
  14233.             SELECT @srvid = @virtual_id 
  14234.         END
  14235.     ELSE
  14236.         BEGIN
  14237.             /* validate name and get subscriber ID  and server status  */
  14238.             EXECUTE @retcode = dbo.sp_validname @subscriber
  14239.             IF @retcode <> 0
  14240.             RETURN (1)
  14241.  
  14242.             SELECT @srvid = srvid
  14243.               FROM master..sysservers
  14244.              WHERE UPPER(srvname) = UPPER(@subscriber) collate database_default
  14245.                AND (srvstatus & @subscriber_bit) <> 0
  14246.  
  14247.             IF @srvid IS NULL
  14248.                 BEGIN
  14249.                     RAISERROR (14010, 16, -1)
  14250.                     RETURN (1)
  14251.                 END
  14252.         END
  14253.  
  14254.     -- Have to check @destination_db before expanding publications and articles
  14255.     -- Otherwise, the error will not be caught because the cursor will return zero row.
  14256.     if @destination_db is not null and LOWER(@destination_db) <> 'all' 
  14257.     begin
  14258.         if not exists (select * from syssubscriptions where
  14259.             srvid = @srvid and
  14260.             dest_db = @destination_db)
  14261.         begin
  14262.             RAISERROR (14055, 11, -1)
  14263.             RETURN (1)
  14264.         end
  14265.     end
  14266.  
  14267.     /*
  14268.     ** If the @publication is 'all', the user wants to cancel all subscriptions
  14269.     ** for all publications associated with the specified @subscriber.
  14270.     */
  14271.  
  14272.     IF LOWER(@publication) = 'all'
  14273.         BEGIN
  14274.             DECLARE hCdrop_subscription2  CURSOR LOCAL FAST_FORWARD FOR 
  14275.                 SELECT DISTINCT a.name 
  14276.                     FROM syspublications a, sysextendedarticlesview b,  syssubscriptions c 
  14277.                     WHERE c.srvid = @srvid
  14278.                     -- @destination_db will not be expanded before @publication is expanded.
  14279.                     AND (c.dest_db = @destination_db 
  14280.                     or @destination_db is null
  14281.                     or LOWER(@destination_db) = 'all')
  14282.                     AND a.pubid = b.pubid 
  14283.                     AND b.artid = c.artid 
  14284.                     
  14285.             OPEN hCdrop_subscription2
  14286.             FETCH hCdrop_subscription2 INTO @publication
  14287.             WHILE (@@fetch_status <> -1)
  14288.                 BEGIN
  14289.                     EXECUTE dbo.sp_dropsubscription @publication = @publication,
  14290.                                                 @article     = 'all',
  14291.                                                 @subscriber  = @subscriber,
  14292.                                                 @destination_db = @destination_db,
  14293.                                                 @ignore_distributor = @ignore_distributor,
  14294.                                                 @reserved = @reserved
  14295.  
  14296.                     FETCH hCdrop_subscription2 INTO @publication
  14297.                 END
  14298.             CLOSE hCdrop_subscription2
  14299.             DEALLOCATE hCdrop_subscription2
  14300.             RETURN (0)
  14301.         END
  14302.  
  14303.     /*
  14304.     ** Parameter Check: @publication.
  14305.     ** Check to make sure that the publication exists and that it conforms
  14306.     ** to the rules for identifiers.
  14307.     */
  14308.  
  14309.     IF @publication IS NULL
  14310.         BEGIN
  14311.             RAISERROR (14043, 16, -1, '@publication')
  14312.             RETURN (1)
  14313.         END
  14314.  
  14315.     EXECUTE @retcode = dbo.sp_validname @publication
  14316.  
  14317.     IF @retcode <> 0
  14318.     RETURN (1)
  14319.  
  14320.     IF NOT EXISTS (SELECT * FROM syspublications WHERE name = @publication)
  14321.         BEGIN
  14322.             RAISERROR (20026, 11, -1, @publication)
  14323.             RETURN (1)
  14324.         END
  14325.  
  14326.     /* Get subscription type of the publication */
  14327.     SELECT @immediate_sync = immediate_sync, @sync_method = sync_method
  14328.         FROM syspublications WHERE name = @publication
  14329.  
  14330.     /*
  14331.     ** Parameter Check:  @article
  14332.     */
  14333.  
  14334.     /* @article can not be null     */
  14335.     IF @article IS NULL
  14336.         BEGIN
  14337.             RAISERROR (14043, 16, -1, '@article')
  14338.             RETURN (1)
  14339.         END
  14340.  
  14341.  
  14342.     /* 
  14343.     ** If publication is of concurrent sync, then all articles must
  14344.     ** be unsubscribed to
  14345.     */
  14346.     /*IF @sync_method in (@concurrent, @concurrent_char) AND
  14347.        LOWER(@article) != 'all' AND
  14348.        @reserved NOT IN( @expand_article, @internal )
  14349.     BEGIN
  14350.         RAISERROR( 14102, 16, -1 )
  14351.         RETURN (1)
  14352.     END*/
  14353.  
  14354.     /** For immediate_sync publication, @article has to be 'all'     */
  14355.     -- Relax this constraint since users will need to do this before dropping
  14356.     -- an article
  14357.     /*
  14358.     IF @reserved <> @internal AND @reserved <> @expand_article
  14359.         AND @immediate_sync = 1
  14360.         AND NOT LOWER(@article) = 'all'
  14361.         BEGIN
  14362.             RAISERROR (14122, 16, -1)
  14363.             RETURN (1)
  14364.         END
  14365.     */
  14366.  
  14367.     /*
  14368.     ** If the @article is 'all', the user wants to cancel all
  14369.     ** subscriptions on this publisher associated with the given @subscriber
  14370.     ** and @publication.
  14371.     */
  14372.  
  14373.     IF LOWER(@article) = 'all'
  14374.         BEGIN
  14375.  
  14376.             /* Make the operation automic for immediate_sync publications */
  14377.             BEGIN TRAN
  14378.  
  14379.             IF @reserved IS NULL
  14380.                 SELECT @reserved = @expand_article
  14381.  
  14382.             DECLARE hCdrop_subscription3  CURSOR LOCAL FAST_FORWARD FOR
  14383.                 SELECT DISTINCT art.name 
  14384.                     FROM sysextendedarticlesview art, syssubscriptions sub, syspublications pub 
  14385.                     WHERE sub.srvid = @srvid
  14386.                     -- @destination_db will not be expanded before @article is expanded.
  14387.                     AND (sub.dest_db = @destination_db 
  14388.                     or @destination_db is null
  14389.                     or LOWER(@destination_db) = 'all')
  14390.                     AND sub.artid = art.artid
  14391.                     AND art.pubid = pub.pubid
  14392.                     AND pub.name = @publication 
  14393.                     
  14394.             OPEN hCdrop_subscription3
  14395.             FETCH hCdrop_subscription3 INTO @article
  14396.             WHILE (@@fetch_status <> -1)
  14397.                 BEGIN
  14398.                     EXECUTE @retcode = dbo.sp_dropsubscription 
  14399.                         @publication = @publication,
  14400.                         @article = @article,
  14401.                         @subscriber = @subscriber,
  14402.                         @destination_db = @destination_db,
  14403.                         @ignore_distributor = @ignore_distributor,
  14404.                         @reserved = @reserved
  14405.                     IF @@error<>0 OR @retcode <> 0
  14406.                     BEGIN
  14407.                         CLOSE hCdrop_subscription3
  14408.                         DEALLOCATE hCdrop_subscription3
  14409.                         GOTO UNDO                        
  14410.                     END
  14411.                     FETCH hCdrop_subscription3 INTO @article
  14412.                 END
  14413.             CLOSE hCdrop_subscription3
  14414.             DEALLOCATE hCdrop_subscription3
  14415.  
  14416.             COMMIT TRAN
  14417.             RETURN (0)
  14418.         END
  14419.  
  14420.     /*
  14421.     ** Parameter Check: @article
  14422.     ** Check if the article exists.
  14423.     */
  14424.  
  14425.     /*
  14426.     EXECUTE @retcode = dbo.sp_validname @article
  14427.  
  14428.     IF @retcode <> 0
  14429.     RETURN (1)
  14430.     */
  14431.  
  14432.     SELECT @artid = artid
  14433.       FROM sysextendedarticlesview art, syspublications pub
  14434.      WHERE pub.name = @publication
  14435.        AND art.name = @article
  14436.        AND art.pubid = pub.pubid
  14437.  
  14438.     IF @artid IS NULL
  14439.         BEGIN
  14440.             RAISERROR (20027, 11, -1, @article)
  14441.         RETURN (1)
  14442.         END
  14443.  
  14444.  
  14445.     /*
  14446.     ** Parameter Check: @destination_db.
  14447.     ** Set @destination_db to current database if not specified.  Make
  14448.     ** sure that the @destination_db conforms to the rules for identifiers.
  14449.     */
  14450.  
  14451.     IF @destination_db IS NULL
  14452.     BEGIN
  14453.         /*
  14454.         ** Check if the subscription exists.
  14455.         */
  14456.  
  14457.         IF NOT EXISTS (SELECT *
  14458.                          FROM syssubscriptions
  14459.                         WHERE srvid = @srvid
  14460.                           AND artid = @artid)
  14461.         BEGIN    
  14462.                 RAISERROR (14055, 11, -1)
  14463.                 RETURN (1)
  14464.         END
  14465.         ELSE
  14466.  
  14467.         SELECT @destination_db = 'all' 
  14468.     END
  14469.     ELSE
  14470.     BEGIN
  14471.         EXECUTE @retcode = dbo.sp_validname @destination_db
  14472.         IF @retcode <> 0
  14473.         RETURN (1)
  14474.     END
  14475.  
  14476.     IF LOWER(@destination_db) = 'all' 
  14477.         BEGIN
  14478.             DECLARE hCdropsub4  CURSOR LOCAL FAST_FORWARD FOR 
  14479.                 SELECT DISTINCT dest_db
  14480.                     FROM syssubscriptions 
  14481.                     WHERE srvid = @srvid
  14482.                     AND artid = @artid
  14483.             OPEN hCdropsub4
  14484.             FETCH hCdropsub4 INTO @destination_db
  14485.             WHILE (@@fetch_status <> -1)
  14486.                 BEGIN
  14487.                     EXECUTE dbo.sp_dropsubscription 
  14488.                         @publication = @publication,
  14489.                         @article = @article,
  14490.                         @subscriber = @subscriber,
  14491.                         @destination_db = @destination_db,
  14492.                         @ignore_distributor = @ignore_distributor,
  14493.                         @reserved = @reserved
  14494.                     FETCH hCdropsub4 INTO @destination_db
  14495.                 END
  14496.             CLOSE hCdropsub4
  14497.             DEALLOCATE hCdropsub4
  14498.             RETURN (0)
  14499.         END
  14500.  
  14501.     /*
  14502.     ** Dropping virtual subscriptions is not allowed
  14503.     ** in following case:
  14504.     ** 1. non sa or dbo user
  14505.     ** 2. the stored procedure is not in internal usage mode 
  14506.     **        (called by system stored procedures)
  14507.     **
  14508.     ** Note: Only immediate_sync publications have virtual subscriptions
  14509.     ** 
  14510.     */
  14511.  
  14512.     IF  @srvid = @virtual_id  AND  (
  14513.         @reserved <> @internal)
  14514.         BEGIN
  14515.             RAISERROR (14056, 16, -1)
  14516.             RETURN (1)
  14517.         END
  14518.  
  14519.     /*
  14520.     ** Check if the subscription exists.
  14521.     */
  14522.  
  14523.     IF NOT EXISTS (SELECT *
  14524.                      FROM syssubscriptions
  14525.                     WHERE srvid = @srvid
  14526.                       AND artid = @artid
  14527.                       AND dest_db = @destination_db)
  14528.     BEGIN
  14529.             RAISERROR (14055, 11, -1)
  14530.             RETURN (1)
  14531.     END
  14532.  
  14533.  
  14534.     /* Check the current login id. It is valid only when
  14535.     ** 1. sa or dbo
  14536.     ** 2. same as the one who add the subscription.
  14537.     */
  14538.     SELECT @login_name = login_name 
  14539.          FROM syssubscriptions
  14540.         WHERE srvid = @srvid
  14541.           AND artid = @artid
  14542.           AND dest_db = @destination_db
  14543.  
  14544.     IF  suser_sname(suser_sid()) <> @login_name AND is_srvrolemember('sysadmin') <> 1  
  14545.         AND is_member ('db_owner') <> 1
  14546.     BEGIN
  14547.             SELECT @qualified_subscription_name = @subscriber + N':' + @destination_db
  14548.             RAISERROR(21120, 11, -1, @qualified_subscription_name, @publication)
  14549.             RETURN (1)
  14550.     END
  14551.  
  14552.  
  14553.     begin tran
  14554.     save TRANSACTION dropsubscription
  14555.  
  14556.         /* If dropping virtual subscriptions, reset immediate_sync_ready bit */
  14557.         IF @srvid = @virtual_id
  14558.         BEGIN
  14559.             UPDATE syspublications SET immediate_sync_ready = 0
  14560.                 WHERE
  14561.                     name = @publication and
  14562.                     immediate_sync = 1 and
  14563.                     immediate_sync_ready = 1
  14564.             IF @@ERROR <> 0
  14565.                 goto UNDO
  14566.         END
  14567.  
  14568.         /*
  14569.         ** Change the status of the subscription to 'inactive'.
  14570.         */
  14571.  
  14572.         EXECUTE @retcode = dbo.sp_changesubstatus @publication = @publication,
  14573.                                               @article = @article,
  14574.                                               @subscriber = @subscriber,
  14575.                                               @status = 'inactive',
  14576.                                               @destination_db = @destination_db,
  14577.                                               @ignore_distributor = @ignore_distributor
  14578.         IF @@ERROR <> 0 OR @retcode <> 0
  14579.         BEGIN
  14580.             if @@trancount > 0
  14581.             begin
  14582.                 ROLLBACK TRANSACTION dropsubscription
  14583.                 commit tran
  14584.             end
  14585.             RETURN (1)
  14586.         END
  14587.  
  14588.     /* Read the subscription_type befor removing the syssubscriptions row */
  14589.     select @subscription_type = subscription_type from syssubscriptions
  14590.         WHERE artid = @artid
  14591.         AND srvid = @srvid
  14592.         AND dest_db = @destination_db
  14593.     /*
  14594.     ** Remove subscription from syssubscriptions.
  14595.     */
  14596.     DELETE syssubscriptions
  14597.      WHERE artid = @artid
  14598.        AND srvid = @srvid
  14599.        AND dest_db = @destination_db
  14600.  
  14601.     IF @@ERROR <> 0
  14602.     BEGIN
  14603.         if @@trancount > 0
  14604.         begin
  14605.             ROLLBACK TRANSACTION dropsubscription
  14606.             commit tran
  14607.         end
  14608.         RETURN (1)
  14609.     END
  14610.  
  14611.     /* Call sp_MSunregistersubscription so that the reg entries get deleted (for push subscriptions) */
  14612.     if @subscription_type = @push
  14613.         begin
  14614.             declare @publisher_db sysname
  14615.             set @publisher_db = DB_NAME()
  14616.             exec @retcode = dbo.sp_MSunregistersubscription @publisher = @@SERVERNAME,
  14617.                                 @publisher_db = @publisher_db,
  14618.                                 @publication = @publication,
  14619.                                 @subscriber = @subscriber,
  14620.                                 @subscriber_db = @destination_db
  14621.  
  14622.             IF @retcode<>0 or @@ERROR<>0
  14623.                 GOTO UNDO
  14624.         end             
  14625.   
  14626.     COMMIT TRANSACTION
  14627.     RETURN (0)
  14628.  
  14629. UNDO:
  14630.     IF @@TRANCOUNT = 1
  14631.         ROLLBACK TRAN
  14632.     ELSE
  14633.         COMMIT TRAN
  14634.     RETURN(1)
  14635. go
  14636.  
  14637. EXEC dbo.sp_MS_marksystemobject sp_dropsubscription
  14638. GO
  14639.  
  14640. print ''
  14641. print 'Creating procedure sp_subscribe'
  14642. go
  14643. CREATE PROCEDURE sp_subscribe (
  14644.     @publication sysname,          /* publication name */
  14645.     @article sysname = 'all',          /* article name */
  14646.     @destination_db sysname = NULL,  /* subscriber database */
  14647.     @sync_type nvarchar (15) = 'automatic' /* subscription sync type */
  14648.     ) AS
  14649.  
  14650.     -- New 7.0 sp_addsubscription parameters
  14651.     DECLARE @subscriber                  sysname
  14652.     DECLARE @status                      sysname
  14653.     DECLARE @subscription_type           nvarchar(4)
  14654.     DECLARE @update_mode                 nvarchar(15)
  14655.     DECLARE @loopback_detection          nvarchar(5)
  14656.     DECLARE @enabled_for_syncmgr         nvarchar(5)
  14657.     DECLARE @retcode                     int
  14658.  
  14659.     SET NOCOUNT ON
  14660.  
  14661.     -- sp_subscribe has to be called from a remote subscriber 
  14662.     -- If not, we state that it is unsupported
  14663.     SELECT @subscriber = @@REMSERVER
  14664.     IF @subscriber IS NULL
  14665.     BEGIN
  14666.       RAISERROR (21023, 16, -1,'sp_subscribe')
  14667.       RETURN(1)
  14668.     END
  14669.     
  14670.     SELECT @status = NULL
  14671.     SELECT @subscription_type = 'push'
  14672.     SELECT @update_mode = 'read only'
  14673.     SELECT @loopback_detection = 'false'
  14674.     SELECT @enabled_for_syncmgr = 'false'
  14675.  
  14676.     -- Call sp_addsubscription to do the actual work
  14677.     EXEC @retcode = dbo.sp_addsubscription @publication = @publication,
  14678.                                            @article = @article,
  14679.                                            @destination_db = @destination_db,
  14680.                                            @sync_type = @sync_type,
  14681.                                            @subscriber = @subscriber,
  14682.                                            @status = @status,
  14683.                                            @subscription_type = @subscription_type,
  14684.                                            @update_mode = @update_mode,
  14685.                                            @loopback_detection = @loopback_detection,
  14686.                                            @enabled_for_syncmgr = @enabled_for_syncmgr
  14687.                                         
  14688.     RETURN @retcode   
  14689. go
  14690.  
  14691. EXEC dbo.sp_MS_marksystemobject sp_subscribe
  14692. GO
  14693.  
  14694. print ''
  14695. print 'Creating procedure sp_unsubscribe'
  14696. go
  14697. CREATE PROCEDURE sp_unsubscribe (
  14698.     @publication sysname = NULL,       /* publication name */
  14699.     @article sysname = NULL            /* article name */
  14700.     ) AS
  14701.  
  14702.     -- New 7.0 sp_dropsubscription parameters
  14703.     DECLARE @subscriber     sysname
  14704.     DECLARE @destination_db sysname    
  14705.     DECLARE @retcode        int 
  14706.  
  14707.     SET NOCOUNT ON
  14708.     
  14709.     -- sp_unsubscribe has to be callled from a remote subscriber
  14710.     -- If not, we state that it is unsupported
  14711.     SELECT @subscriber = @@REMSERVER
  14712.     IF @subscriber IS NULL
  14713.     BEGIN
  14714.         RAISERROR (21023, 16, -1,'sp_unsubscribe')
  14715.         RETURN(1)
  14716.     END
  14717.  
  14718.     -- 6.5 didn't support having multiple databases on the same subscriber
  14719.     -- subscribing to the same publication so here, all subscriptions to the
  14720.     -- same publication will be dropped 
  14721.     SELECT @destination_db = NULL
  14722.     
  14723.     -- Call sp_dropsubscription to do the real work
  14724.     EXEC @retcode = sp_dropsubscription @publication = @publication,
  14725.                                         @article = @article,
  14726.                                         @subscriber = @subscriber,
  14727.                                         @destination_db = @destination_db
  14728.     RETURN @retcode
  14729.     
  14730. go
  14731.  
  14732. EXEC dbo.sp_MS_marksystemobject sp_unsubscribe
  14733. GO
  14734.  
  14735. print ''
  14736. print 'Creating procedure sp_refreshsubscriptions'
  14737. go
  14738.  
  14739. CREATE PROCEDURE sp_refreshsubscriptions (
  14740.     @publication sysname       /* Publication name */
  14741.     ) AS
  14742.  
  14743.     SET NOCOUNT ON
  14744.  
  14745.     /*
  14746.     ** Declarations.
  14747.     */
  14748.  
  14749.     DECLARE @article  sysname 
  14750.     DECLARE @subscriber sysname
  14751.     DECLARE @dest_db sysname
  14752.     DECLARE @retcode int
  14753.     DECLARE @pubid int
  14754.     DECLARE @immediate_sync bit 
  14755.     DECLARE @no_sync tinyint
  14756.     DECLARE @subscription_type_id int
  14757.     DECLARE @subscription_type nvarchar(4)
  14758.     DECLARE @virtual smallint
  14759.     DECLARE @srvid smallint
  14760.     DECLARE @sync_typeid int
  14761.     DECLARE @automatic tinyint
  14762.     DECLARE @sync_type nvarchar(9)
  14763.  
  14764.     SELECT @no_sync = 2
  14765.     SELECT @virtual = -1
  14766.     SELECT @automatic = 1
  14767.     /*
  14768.     ** Security Check
  14769.     */
  14770.     exec @retcode = dbo.sp_MSreplcheck_publish
  14771.     if @@ERROR <> 0 or @retcode <> 0
  14772.         return(1)
  14773.  
  14774.     /*
  14775.     ** Check to see if the database has been activated for publication.
  14776.     */
  14777.  
  14778.     IF (SELECT category & 1
  14779.           FROM master..sysdatabases
  14780.          WHERE name = DB_NAME() collate database_default) = 0
  14781.  
  14782.     BEGIN
  14783.             RAISERROR (14013, 16, -1)
  14784.         RETURN (1)
  14785.     END
  14786.  
  14787.  
  14788.     /*
  14789.     ** Parameter Check:  @publication.
  14790.     ** Make sure that the publication exists
  14791.     */
  14792.  
  14793.     IF @publication IS NULL
  14794.         BEGIN
  14795.             RAISERROR (14043, 16, -1, '@publication')
  14796.             RETURN (1)
  14797.         END
  14798.  
  14799.     EXECUTE @retcode = dbo.sp_validname @publication
  14800.  
  14801.     IF @@ERROR <> 0 OR @retcode <> 0
  14802.     RETURN (1)
  14803.  
  14804.     SELECT @pubid = pubid
  14805.         FROM syspublications WHERE name = @publication
  14806.  
  14807.     IF @pubid IS NULL
  14808.         BEGIN
  14809.             RAISERROR (20026, 11, -1, @publication)
  14810.             RETURN (1)
  14811.         END
  14812.     
  14813.     
  14814.     /* Add real subscription to the new articles  */
  14815.     /* Open a cursor on all the pending subscriptions, that is */
  14816.     /* All the subscriptions on the publication that */
  14817.     /* are not on an article in the publication. */
  14818.     /* not including virtual subscriptions */
  14819.  
  14820.     DECLARE hCrefreshsubscriptions CURSOR LOCAL FAST_FORWARD FOR
  14821.         SELECT DISTINCT art1.name, subs1.dest_db, subs1.srvid
  14822.             FROM syssubscriptions subs1, sysextendedarticlesview art1
  14823.             WHERE art1.pubid = @pubid AND
  14824.                   subs1.srvid <> @virtual AND
  14825.                   EXISTS (SELECT * FROM syssubscriptions subs2, sysextendedarticlesview art2
  14826.                     WHERE subs2.srvid = subs1.srvid AND
  14827.                           subs2.dest_db = subs1.dest_db AND
  14828.                           subs2.artid = art2.artid AND
  14829.                           art2.pubid = @pubid) AND
  14830.                   NOT EXISTS ( SELECT * FROM syssubscriptions subs3 
  14831.                     WHERE  subs3.artid = art1.artid AND
  14832.                            subs3.srvid = subs1.srvid AND
  14833.                            subs3.dest_db = subs1.dest_db)
  14834.     FOR READ ONLY
  14835.     OPEN hCrefreshsubscriptions
  14836.     FETCH hCrefreshsubscriptions INTO @article,  @dest_db, @srvid
  14837.             
  14838.     
  14839.     WHILE (@@fetch_status <> -1)
  14840.     BEGIN
  14841.  
  14842.         /* 
  14843.         ** Get subscription type on the publication
  14844.         */ 
  14845.         SELECT @subscription_type_id = subs.subscription_type,
  14846.             @sync_typeid = subs.sync_type
  14847.          from 
  14848.             sysextendedarticlesview art, syssubscriptions subs where 
  14849.             art.pubid = @pubid AND
  14850.             subs.srvid = @srvid AND
  14851.             subs.dest_db = @dest_db AND
  14852.             subs.artid = art.artid
  14853.  
  14854.         /* 
  14855.         ** only do it if the subscription all have the same subscription type
  14856.         ** and sync_type
  14857.         */
  14858.         IF NOT EXISTS (SELECT * from 
  14859.             sysextendedarticlesview art, syssubscriptions subs where 
  14860.             art.pubid = @pubid AND
  14861.             subs.srvid = @srvid AND
  14862.             subs.dest_db = @dest_db AND
  14863.             subs.artid = art.artid AND
  14864.             (subscription_type <> @subscription_type_id OR
  14865.             sync_type <> @sync_typeid))
  14866.         BEGIN
  14867.             IF @subscription_type_id = 0
  14868.                 SELECT @subscription_type = 'push'
  14869.             ELSE
  14870.                 SELECT @subscription_type = 'pull'
  14871.  
  14872.             if @sync_typeid = @automatic
  14873.                 SELECT @sync_type = 'automatic'
  14874.             else
  14875.                 SELECT @sync_type = 'none'
  14876.  
  14877.             /* 
  14878.             ** Get the server name
  14879.             */
  14880.             SELECT @subscriber = srvname FROM master.dbo.sysservers 
  14881.                 WHERE srvid = @srvid
  14882.  
  14883.             EXECUTE @retcode  = dbo.sp_addsubscription 
  14884.                         @publication = @publication, 
  14885.                         @article = @article, 
  14886.                         @subscriber = @subscriber, 
  14887.                         @destination_db = @dest_db, 
  14888.                         @sync_type = @sync_type, 
  14889.                         @status = NULL, 
  14890.                         @subscription_type = @subscription_type,
  14891.                         @reserved = 'internal'
  14892.             IF @@ERROR <> 0 OR @retcode <> 0
  14893.             BEGIN
  14894.                 CLOSE hCrefreshsubscriptions
  14895.                 DEALLOCATE hCrefreshsubscriptions
  14896.                 RETURN (1)
  14897.             END
  14898.         END
  14899.         FETCH hCrefreshsubscriptions INTO @article, @dest_db, @srvid
  14900.     END
  14901.     
  14902.     CLOSE hCrefreshsubscriptions
  14903.     DEALLOCATE hCrefreshsubscriptions
  14904.  
  14905. GO
  14906.  
  14907. EXEC dbo.sp_MS_marksystemobject sp_refreshsubscriptions
  14908. GO
  14909.  
  14910. print ''
  14911. print 'Creating procedure sp_MSpublishdb'
  14912. go
  14913.  
  14914. CREATE PROCEDURE sp_MSpublishdb(
  14915.       @value     sysname,
  14916.       @ignore_distributor bit = 0
  14917.     ) AS
  14918.  
  14919.     SET NOCOUNT ON
  14920.  
  14921.     /*
  14922.     ** Declarations.
  14923.     */
  14924.     declare @quoted_db      sysname
  14925.     declare @db_name        sysname
  14926.     declare @command        nvarchar(255)
  14927.     declare @description    nvarchar(500)
  14928.     declare @category_name  nvarchar(100)
  14929.     DECLARE @agentname      nvarchar(300)
  14930.     DECLARE @dbname         sysname 
  14931.     DECLARE @retcode        int
  14932.     DECLARE @distributor    sysname
  14933.     DECLARE @distribdb      sysname
  14934.     DECLARE @distproc       nvarchar (255)
  14935.     /*
  14936.     ** Initialization
  14937.     */
  14938.  
  14939.     SELECT @dbname = DB_NAME()
  14940.  
  14941.     /*
  14942.     ** Parameter check
  14943.     ** @value
  14944.     */
  14945.     IF LOWER(@value) NOT IN ('true','false')
  14946.     BEGIN
  14947.       RAISERROR(14137,16,-1)
  14948.       RETURN(1)
  14949.     END
  14950.  
  14951.     /*
  14952.     ** if @ignore_distributor = 1, we are in bruteforce cleanup mode, don't do RPC.
  14953.     */
  14954.     if @ignore_distributor = 0
  14955.     begin
  14956.         /*
  14957.         ** Test to see if the distributor is installed and online.
  14958.         */
  14959.         EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  14960.            @distribdb   = @distribdb OUTPUT
  14961.  
  14962.         IF @@ERROR <> 0 or @retcode <> 0 or @distributor IS NULL or @distribdb IS NULL
  14963.         BEGIN
  14964.             IF LOWER(@value) = 'true'
  14965.                 RAISERROR (20028, 16, -1)
  14966.             ELSE
  14967.                 RAISERROR (20029, 16, -1)
  14968.             RETURN (1)
  14969.         END
  14970.     end
  14971.  
  14972.     /*
  14973.     ** Enable the database for publishing.
  14974.     */
  14975.     IF LOWER(@value) = 'true'
  14976.     BEGIN
  14977.  
  14978.         /*
  14979.         ** Drop and then create central publish tables
  14980.         */
  14981.  
  14982.         /* 
  14983.         ** Drop first if exists
  14984.         */
  14985.  
  14986.         EXEC @retcode = dbo.sp_MSdrop_pub_tables
  14987.         IF @@ERROR <> 0 or @retcode <> 0
  14988.         BEGIN
  14989.             return (1)
  14990.         END
  14991.  
  14992.         /*
  14993.         ** Create central publish tables
  14994.         */
  14995.  
  14996.         EXEC @retcode = dbo.sp_MScreate_pub_tables
  14997.         IF @@ERROR <> 0 or @retcode <> 0
  14998.         BEGIN
  14999.             return (1)
  15000.         END
  15001.     END
  15002.  
  15003.     ELSE    /* Disable the database for publishing. */
  15004.     BEGIN
  15005.         /*
  15006.         ** Remove all subscriptions in the database.
  15007.         ** WARNING : must owner qualify proc calls for these to run inside server on restore/attach
  15008.         */
  15009.         EXEC @retcode = dbo.sp_dropsubscription @publication = 'all',
  15010.             @article = 'all', @subscriber = 'all', 
  15011.             @ignore_distributor = @ignore_distributor
  15012.         IF @@ERROR <> 0 or @retcode <> 0
  15013.         BEGIN
  15014.             return (1)
  15015.         END
  15016.  
  15017.         -- Used for attach and restored db.
  15018.         -- sysservers table in master db might be changed so that
  15019.         -- sp_dropsubscription won't work. Delete the table directly.
  15020.  
  15021.         delete syssubscriptions where srvid >= 0
  15022.         IF @@ERROR <> 0 
  15023.         BEGIN
  15024.             return (1)
  15025.         END
  15026.  
  15027.         /*
  15028.         ** Remove all publications and articles in the database.
  15029.         ** sp_droppublication will also forcefully unmark repl bits in sysobjects
  15030.         ** and call sp_repldone when dropping the last
  15031.         ** publication.
  15032.         */
  15033.         EXEC @retcode = dbo.sp_droppublication @publication = 'all', 
  15034.             @ignore_distributor = @ignore_distributor
  15035.         IF @@ERROR <> 0 or @retcode <> 0
  15036.         BEGIN
  15037.             return (1)
  15038.         END
  15039.  
  15040.         /* 
  15041.         ** Drop central publish tables
  15042.         */ 
  15043.         EXEC @retcode = dbo.sp_MSdrop_pub_tables
  15044.         IF @@ERROR <> 0 or @retcode <> 0
  15045.         BEGIN
  15046.             return (1)
  15047.         END
  15048.  
  15049.       END
  15050.     return (0)
  15051. GO
  15052.  
  15053. EXEC dbo.sp_MS_marksystemobject sp_MSpublishdb
  15054. GO
  15055.  
  15056. print ''
  15057. print 'Creating procedure sp_MSactivate_auto_sub'
  15058. go
  15059.  
  15060. CREATE PROCEDURE sp_MSactivate_auto_sub (
  15061.     @publication sysname,        /* Publication name */
  15062.     @article sysname,
  15063.     @status sysname = 'active',
  15064.     @schemastabilityonly int = 0
  15065.     ) AS
  15066.  
  15067.     SET NOCOUNT ON
  15068.  
  15069.     DECLARE @retcode int
  15070.  
  15071.     /*
  15072.     ** Security Check.
  15073.     */
  15074.     exec @retcode = dbo.sp_MSreplcheck_publish
  15075.     if @@ERROR <> 0 or @retcode <> 0
  15076.         return(1)
  15077.  
  15078.     /*
  15079.     ** Check to see if the database has been activated for publication.
  15080.     */
  15081.  
  15082.     IF (SELECT category & 1
  15083.           FROM master..sysdatabases
  15084.          WHERE name = DB_NAME() collate database_default) = 0
  15085.  
  15086.     BEGIN
  15087.         RAISERROR (14013, 16, -1)
  15088.         RETURN (1)
  15089.     END
  15090.  
  15091.     -- parameter check: @status:  
  15092.  
  15093.     IF LOWER(@status) not in (N'active', N'initiated')
  15094.     BEGIN
  15095.         RAISERROR(21156, 16, -1)
  15096.         RETURN 1
  15097.     END
  15098.  
  15099.     /*
  15100.     ** Parameter Check:  @publication.
  15101.     ** Make sure that the publication exists and the publication is not push type
  15102.     */
  15103.  
  15104.     IF @publication IS NULL
  15105.         BEGIN
  15106.             RAISERROR (14043, 16, -1, '@publication')
  15107.             RETURN (1)
  15108.         END
  15109.  
  15110.     EXECUTE @retcode = dbo.sp_validname @publication
  15111.     IF @@ERROR <> 0 OR @retcode <> 0
  15112.         RETURN (1)
  15113.     
  15114.     BEGIN TRAN
  15115.  
  15116.     IF @status = N'active'
  15117.     BEGIN
  15118.         UPDATE syspublications SET immediate_sync_ready = 1 
  15119.             WHERE
  15120.                 name = @publication AND
  15121.                 immediate_sync = 1 AND
  15122.                 immediate_sync_ready <> 1
  15123.         IF @@ERROR <> 0
  15124.         BEGIN
  15125.             GOTO UNDO
  15126.             RETURN (1)
  15127.         END
  15128.     END
  15129.  
  15130.     EXECUTE @retcode = dbo.sp_changesubstatus 
  15131.         @publication = @publication,
  15132.         @article = @article,
  15133.         @status = @status,
  15134.         @from_auto_sync = 1,
  15135.         @schemastabilityonly = @schemastabilityonly
  15136.  
  15137.     IF @@ERROR <> 0 OR @retcode <> 0
  15138.     BEGIN
  15139.         GOTO UNDO
  15140.         RETURN (1)
  15141.     END
  15142.     
  15143.     COMMIT TRAN
  15144.     RETURN(0)
  15145.  
  15146. UNDO:
  15147.     IF @@TRANCOUNT = 1
  15148.         ROLLBACK TRAN
  15149.     ELSE
  15150.         COMMIT TRAN
  15151.  
  15152. GO
  15153.  
  15154. EXEC dbo.sp_MS_marksystemobject sp_MSactivate_auto_sub
  15155. GO
  15156.  
  15157. raiserror('Creating procedure sp_MSget_synctran_commands', 0,1)
  15158. GO
  15159. CREATE PROCEDURE sp_MSget_synctran_commands(
  15160.     @publication sysname    /* publication name */,
  15161.     @article sysname = 'all',
  15162.     @command_only bit = 0   /* 0 if called by snapshot agent, 1 if called by sp_script_..., */
  15163. ) AS
  15164. BEGIN
  15165.     SET NOCOUNT ON
  15166.     DECLARE @artid int
  15167.             ,@tabid int
  15168.             ,@retcode int
  15169.             ,@art_type tinyint        
  15170.             ,@filter_id int
  15171.             ,@filter_clause nvarchar(4000)
  15172.             ,@columns binary(32)
  15173.             ,@distributor sysname
  15174.             ,@pubid int
  15175.             ,@art_name sysname 
  15176.             ,@posted_synctran_artid int
  15177.             ,@dest_table sysname 
  15178.             ,@dest_owner sysname
  15179.             ,@proc_owner sysname
  15180.  
  15181.             ,@ts_col sysname
  15182.             ,@replcmd nvarchar(4000)
  15183.             ,@insproc sysname
  15184.             ,@updproc sysname
  15185.             ,@delproc sysname
  15186.             ,@cftproc sysname
  15187.             ,@cft_table sysname
  15188.             ,@is_synctran bit
  15189.             ,@is_queued bit
  15190.             ,@identity_col sysname
  15191.             ,@identity_prop tinyint
  15192.             ,@identity_support bit
  15193.  
  15194.  
  15195.     /*
  15196.     ** Initializations.
  15197.     */
  15198.     select @posted_synctran_artid = 0 
  15199.     select @identity_support = 0
  15200.  
  15201.     /* 
  15202.     ** Security Check.
  15203.     ** We use login_name stored in syssubscriptions to manage security 
  15204.     ** Do a relaxed security check here.
  15205.     */
  15206.     exec @retcode = dbo.sp_MSreplcheck_publish
  15207.     if @@ERROR <> 0 or @retcode <> 0
  15208.         return(1)
  15209.  
  15210.     /*
  15211.     ** Parameter Check:  @publication
  15212.     ** Check to make sure that the publication exists, that it's not NULL,
  15213.     ** and that it conforms to the rules for identifiers.
  15214.     */
  15215.  
  15216.     IF @publication IS NULL
  15217.         BEGIN
  15218.             RAISERROR (14043, 16, -1, '@publication')
  15219.             RETURN (1)
  15220.         END
  15221.  
  15222.     EXECUTE @retcode = dbo.sp_validname @publication
  15223.     IF @@ERROR <> 0 OR @retcode <> 0
  15224.     RETURN (1)
  15225.  
  15226.     declare @independent_agent bit
  15227.     SELECT @pubid = pubid,
  15228.             @independent_agent = independent_agent,
  15229.             @is_synctran = allow_sync_tran,
  15230.             @is_queued = allow_queued_tran
  15231.     FROM syspublications 
  15232.     WHERE name = @publication
  15233.  
  15234.     IF @pubid IS NULL
  15235.     BEGIN
  15236.         RAISERROR (20026, 11, -1, @publication)
  15237.         RETURN (1)
  15238.     END
  15239.  
  15240.     -- If the publication does not allow sync tran or queued tran return nothing
  15241.     IF (@is_synctran = 0 AND @is_queued = 0)
  15242.         RETURN(0)
  15243.  
  15244.     --
  15245.     -- get the distributor details for this publisher
  15246.     --
  15247.     exec @retcode = dbo.sp_helpdistributor @distributor = @distributor OUTPUT
  15248.     if (@@ERROR != 0 OR @retcode != 0 or @distributor IS NULL)
  15249.     begin
  15250.         raiserror('sp_MSget_synctran_commands(debug): could not get distributor info', 16, 1)
  15251.         RETURN (1)
  15252.     end
  15253.  
  15254.     CREATE TABLE #art_commands (artid int NOT NULL, commands nvarchar(4000) collate database_default null, id int identity NOT NULL)
  15255.     
  15256.     declare @all_article bit 
  15257.  
  15258.     if lower(@article) = 'all'
  15259.         select @all_article = 1
  15260.     else
  15261.         select @all_article = 0
  15262.  
  15263.     -- Construct ver check cmd
  15264.     declare @ver_check_cmd nvarchar(4000)
  15265.     -- Construct message.
  15266.     select @ver_check_cmd = formatmessage(21273)
  15267.     select @ver_check_cmd = '''' + replace(@ver_check_cmd, '''', '''''') + ''''
  15268.     select @ver_check_cmd = 'if @@microsoftversion<0x07320000 raiserror(' + 
  15269.         @ver_check_cmd + ',16, -1)'
  15270.  
  15271.     DECLARE hCsynctran_arts CURSOR LOCAL FAST_FORWARD FOR
  15272.         SELECT art.artid,
  15273.                art.objid,
  15274.                
  15275.                art.dest_table,
  15276.                art.dest_owner,
  15277.                art.name,
  15278.                art.type,
  15279.                art.filter,
  15280.                art.columns
  15281.           FROM sysarticles art,
  15282.                syspublications pub
  15283.          WHERE pub.pubid = @pubid and
  15284.                pub.pubid = art.pubid and
  15285.                (art.type & 0x1) = 1 and
  15286.                (art.name = @article or
  15287.                @all_article = 1)
  15288.     FOR READ ONLY
  15289.  
  15290.     OPEN hCsynctran_arts
  15291.  
  15292.     FETCH hCsynctran_arts INTO @artid, @tabid, @dest_table, @dest_owner, @art_name, 
  15293.         @art_type, @filter_id, @columns
  15294.     
  15295.     WHILE (@@fetch_status <> -1)
  15296.     BEGIN
  15297.  
  15298.     /*
  15299.     ** Determine conflict detection method 
  15300.     */
  15301.         -- Determine if table has timestamp property
  15302.         select @ts_col = NULL
  15303.         if ObjectProperty(@tabid, 'TableHasTimestamp') = 1 
  15304.         begin
  15305.             exec dbo.sp_MSis_col_replicated @publication, @art_name, 
  15306.                 'timestamp', @ts_col OUTPUT
  15307.         end
  15308.  
  15309.         select @posted_synctran_artid = @artid
  15310.  
  15311.         select @insproc = null, @updproc = null, @delproc = null
  15312.  
  15313.         -- Get sproc names and owner name of the sprocs
  15314.         -- Note artid is unique
  15315.         select @insproc = o.name, @proc_owner = u.name from sysobjects o, sysarticleupdates a, sysusers u
  15316.         where a.artid = @artid and a.sync_ins_proc = o.id and
  15317.             u.uid = o.uid
  15318.  
  15319.         select @updproc = o.name from sysobjects o, sysarticleupdates a
  15320.         where a.artid = @artid and a.sync_upd_proc = o.id
  15321.     
  15322.         select @delproc = o.name from sysobjects o, sysarticleupdates a
  15323.         where a.artid = @artid and a.sync_del_proc = o.id 
  15324.  
  15325.         select @cftproc = o.name from sysobjects o, sysarticleupdates a
  15326.         where a.artid = @artid and a.ins_conflict_proc = o.id 
  15327.         
  15328.         if @insproc IS NULL
  15329.         begin
  15330.             CLOSE hCsynctran_arts
  15331.             DEALLOCATE hCsynctran_arts
  15332.             RAISERROR (14043, 11, -1, '@insproc')
  15333.             RETURN (1)
  15334.         end
  15335.  
  15336.         if @updproc IS NULL 
  15337.         begin
  15338.             CLOSE hCsynctran_arts
  15339.             DEALLOCATE hCsynctran_arts
  15340.             RAISERROR (14043, 11, -1, '@updproc')
  15341.             RETURN (1)
  15342.         end
  15343.  
  15344.         if @delproc IS NULL
  15345.         begin
  15346.             CLOSE hCsynctran_arts
  15347.             DEALLOCATE hCsynctran_arts
  15348.             RAISERROR (14043, 11, -1, '@delproc')
  15349.             RETURN (1)
  15350.         end
  15351.  
  15352.         if (@cftproc IS NULL)
  15353.         begin
  15354.             if (@is_queued = 1)
  15355.             begin
  15356.                 CLOSE hCsynctran_arts
  15357.                 DEALLOCATE hCsynctran_arts
  15358.                 RAISERROR (14043, 11, -1, '@cftproc')
  15359.                 RETURN (1)
  15360.             end            
  15361.         end
  15362.  
  15363.         -- Determine if published table has identity  col
  15364.         select @identity_col = NULL
  15365.         select @identity_support = 0
  15366.         if ObjectProperty(@tabid, 'TableHasIdentity') = 1 
  15367.             exec @retcode = dbo.sp_MSis_col_replicated @publication, @art_name, 'identity', @identity_col OUTPUT
  15368.         if @identity_col is not null
  15369.             select @identity_support = identity_support from sysarticleupdates where artid = @artid
  15370.                 
  15371.         -- Horizontal partition
  15372.         select @filter_clause = 'null'
  15373.         if @filter_id <> 0
  15374.         begin
  15375.             -- We don't handle manual filters;  allow all updates
  15376.             if ((@art_type & 0x3) <> 0x3) 
  15377.                 select @filter_clause = RTRIM(LTRIM(CONVERT(nvarchar(4000), filter_clause)))
  15378.                      from sysarticles where artid = @artid
  15379.         end
  15380.     
  15381.         declare @fullname nvarchar(512)
  15382.         declare @indkey       int
  15383.         declare @indid        int
  15384.         declare @key          sysname
  15385.         declare @col          sysname
  15386.         declare @this_col      int
  15387.         declare @src_cols      int
  15388.         declare @primary_key_bitmap varbinary(4000)
  15389.         declare @byte varbinary(1)
  15390.         declare @i_byte            int
  15391.         declare @num_bytes        int
  15392.         declare @i_bit            tinyint    
  15393.         declare @bitmap_str    varchar(8000)
  15394.         declare @bitmap            varbinary(4000)
  15395.  
  15396.  
  15397.         -- Get qualified name
  15398.         exec dbo.sp_MSget_qualified_name @tabid, @fullname output
  15399.         
  15400.         -- Get number of columns in the partition.
  15401.         exec dbo.sp_MSget_col_position @tabid, @columns, @key, @col output, 
  15402.             @this_col output, 
  15403.             1, -- Get num of columns in the partition.
  15404.             @src_cols output
  15405.         select @num_bytes = @src_cols / 8 + 1
  15406.     
  15407.         -- Set varbinary length
  15408.         set @byte = 0
  15409.         set @primary_key_bitmap = @byte
  15410.         set @i_byte = 1
  15411.         while @i_byte < @num_bytes
  15412.         begin
  15413.             set @primary_key_bitmap = @primary_key_bitmap + @byte
  15414.             set @i_byte = @i_byte + 1
  15415.         end
  15416.     
  15417.         -- get index id
  15418.         exec @indid = dbo.sp_MStable_has_unique_index @tabid
  15419.         set @indkey = 1
  15420.         while @indkey < 16 and index_col(@fullname, @indid, @indkey) is not null
  15421.         begin
  15422.             set @key = index_col(@fullname, @indid, @indkey)
  15423.             exec dbo.sp_MSget_col_position @tabid, @columns, @key, @col output, @this_col output
  15424.             set @i_byte = 1 + (@this_col-1) / 8
  15425.             set @i_bit  = power(2, (@this_col-1) % 8 )
  15426.             set @primary_key_bitmap 
  15427.                 = substring(@primary_key_bitmap, 1, @i_byte - 1)
  15428.                 + convert(binary(1), substring(@primary_key_bitmap, @i_byte, 1) | @i_bit)
  15429.                 + substring(@primary_key_bitmap, @i_byte + 1, @num_bytes - @i_byte)
  15430.             select @indkey = @indkey + 1
  15431.         end
  15432.         exec @retcode = master..xp_varbintohexstr @primary_key_bitmap, @bitmap_str output
  15433.         if @retcode <> 0 or @@error <> 0
  15434.             return 1
  15435.  
  15436.         if @dest_owner is null 
  15437.         begin
  15438.             select @dest_owner = N'null'
  15439.         end
  15440.         select @replcmd = '{call sp_addsynctriggers (N' + 
  15441.             quotename(@dest_table,'''') + ', N' + 
  15442.             quotename(@dest_owner,'''') + ', N' +  
  15443.             quotename(@@SERVERNAME,'''') + ', N' +   
  15444.             quotename(db_name(),'''') + ', N' + 
  15445.             quotename(@publication,'''') + ', N' +  
  15446.             quotename(@insproc,'''') + ', N' +   
  15447.             quotename(@updproc,'''') + ', N' +   
  15448.             quotename(@delproc,'''') + ', N' + 
  15449.             ISNULL(quotename(@cftproc,''''), '''null''')  + ', N' + 
  15450.             quotename(@proc_owner,'''') + ', N' + 
  15451.             ISNULL(quotename(@identity_col,''''),'''null''') + ', N' + 
  15452.             ISNULL(quotename(@ts_col,''''), '''null''') + ', N''' + 
  15453.             replace(@filter_clause,'''', '''''')  + ''', ' + 
  15454.             @bitmap_str   + ', ' + 
  15455.             convert(nvarchar(2), @identity_support)  + ',' +
  15456.             convert(nvarchar(2), @independent_agent) + ',N' +
  15457.             quotename(@distributor,'''') +   
  15458.             ' )}'
  15459.  
  15460.         -- Must add ver check cmd for each article since user can subscribe
  15461.         -- to just one article.    
  15462.         insert into #art_commands values (@artid, @ver_check_cmd)                        
  15463.         insert into #art_commands values (@artid, @replcmd)
  15464.  
  15465.         --
  15466.         -- If we are processing queued publications, insert another command
  15467.         -- to populate MSsubsciption_articles for this article
  15468.         --
  15469.         if (@is_queued = 1)
  15470.         begin
  15471.             select @cft_table = OBJECT_NAME(conflict_tableid) 
  15472.             from sysarticleupdates
  15473.             where artid = @artid and pubid = @pubid
  15474.  
  15475.             if (@cft_table IS NULL)
  15476.             begin
  15477.                 CLOSE hCsynctran_arts
  15478.                 DEALLOCATE hCsynctran_arts
  15479.                 raiserror('Debug: article %s in publication % should have valid conflict table', 
  15480.                     16, 1, @art_name, @publication)
  15481.                 return 1                
  15482.             end
  15483.  
  15484.             --
  15485.             -- add another command
  15486.             --
  15487.             select @replcmd = '{call sp_addqueued_artinfo (' + 
  15488.                 cast(@artid as nvarchar(10)) collate database_default + ', N' +
  15489.                 quotename(@art_name,'''') collate database_default + ', N' +                 
  15490.                 quotename(@@SERVERNAME,'''') collate database_default + ', N' +   
  15491.                 quotename(db_name(),'''') collate database_default + ', N' + 
  15492.                 quotename(@publication,'''') collate database_default + ', N' +  
  15493.                 quotename(@dest_table,'''') collate database_default + ', N' + 
  15494.                 quotename(@dest_owner,'''') collate database_default + ', N' +   
  15495.                 quotename(@cft_table,'''') collate database_default + ', ' +
  15496.                 master.dbo.fn_varbintohexstr(@columns) collate database_default + ' )}'
  15497.             
  15498.             -- Must add ver check cmd for each article since user can subscribe
  15499.             -- to just one article.    
  15500.             insert into #art_commands values (@artid, @ver_check_cmd)                        
  15501.             insert into #art_commands values (@artid, @replcmd)                        
  15502.         end
  15503.  
  15504.         FETCH hCsynctran_arts INTO @artid, @tabid, @dest_table, @dest_owner, @art_name, 
  15505.             @art_type, @filter_id, @columns
  15506.     end
  15507.  
  15508.     -- end SyncTran
  15509.     if @command_only = 0 
  15510.         select * from #art_commands order by id
  15511.     else
  15512.         select commands from #art_commands order by id
  15513.  
  15514.     CLOSE hCsynctran_arts
  15515.     DEALLOCATE hCsynctran_arts
  15516.  
  15517.     return 0
  15518. END
  15519. go
  15520.  
  15521. EXEC dbo.sp_MS_marksystemobject sp_MSget_synctran_commands
  15522. GO
  15523.  
  15524. raiserror('Creating procedure sp_script_synctran_commands', 0,1)
  15525. GO
  15526. CREATE PROCEDURE sp_script_synctran_commands(
  15527.     @publication sysname,    /* publication name */
  15528.     @article sysname = 'all'    /* article name, all means all article */
  15529. ) AS
  15530.     declare @retcode int
  15531.     exec @retcode = dbo.sp_MSget_synctran_commands 
  15532.         @publication = @publication,
  15533.         @article = @article,
  15534.         @command_only = 1
  15535.     if @retcode <> 0 or @@error <> 0
  15536.         return (1)
  15537.  
  15538. go
  15539.  
  15540. dump tran master with no_log
  15541. go
  15542.  
  15543. EXEC dbo.sp_MS_marksystemobject sp_script_synctran_commands
  15544. GO
  15545.  
  15546. print ''
  15547. print 'Creating procedure sp_MSaddpub_snapshot'
  15548. go
  15549. CREATE PROCEDURE sp_MSaddpub_snapshot (
  15550.     @publication sysname,    
  15551.     @freqtype  int = 4 ,                  /* 4== Daily */
  15552.     @freqinterval int  = 1,             /* Every day */
  15553.     @freqsubtype int =  4,                 /* Sub interval = Minute */
  15554.     @freqsubinterval int = 5,              /* Every five minutes */
  15555.     @freqrelativeinterval int = 1, 
  15556.     @freqrecurrencefactor int = 0, 
  15557.     @activestartdate int = 0,             /* 12:00 am - 11:59 pm */
  15558.     @activeenddate int =99991231 ,         /* No start date */    
  15559.     @activestarttimeofday int = 0,         
  15560.     @activeendtimeofday int = 235959,     /* No end time */       
  15561.     @newagentid int = 0 OUTPUT,
  15562.     @snapshot_job_name nvarchar(100) = null
  15563. ) AS
  15564.  
  15565.  
  15566.     SET NOCOUNT ON
  15567.  
  15568.     /*
  15569.     ** Declarations.
  15570.     */
  15571.     DECLARE @retcode            int
  15572.     DECLARE @distributor        sysname
  15573.     DECLARE @distribdb          sysname
  15574.     DECLARE @distproc           nvarchar (255)
  15575.     DECLARE @agentname          nvarchar(100)
  15576.     DECLARE @database           sysname
  15577.     DECLARE @newid              int
  15578.     DECLARE @mergepublish_bit   smallint
  15579.     DECLARE @centralpublish_bit int
  15580.     DECLARE @fFoundPublication  int
  15581.     DECLARE @agent_args         nvarchar(4000)
  15582.     DECLARE @snapshot_jobid     binary(16)
  15583.     DECLARE @dist_rpcname       sysname
  15584.     DECLARE @publication_type   int
  15585.     DECLARE @job_existing       bit
  15586.  
  15587.     /*
  15588.     ** Initializations
  15589.     */
  15590.     select @mergepublish_bit    = 4
  15591.     select @centralpublish_bit  = 1
  15592.     select @fFoundPublication   = 0
  15593.     if (@snapshot_job_name is null) or (@snapshot_job_name = N'')
  15594.     begin
  15595.         select @job_existing = 0
  15596.     end 
  15597.     else
  15598.     begin
  15599.         select @job_existing = 1
  15600.     end
  15601.  
  15602.     EXEC @retcode = dbo.sp_helppublication @publication, @fFoundPublication output
  15603.  
  15604.     IF @@ERROR <> 0 OR @retcode <> 0
  15605.     BEGIN
  15606.         RETURN (1)
  15607.     END
  15608.         
  15609.     IF @fFoundPublication = 0 
  15610.     BEGIN
  15611.         SELECT @newagentid = 0
  15612.         RETURN (0)
  15613.     END
  15614.  
  15615.         
  15616.     /* 
  15617.     ** Make sure the publication does not already have a agent.
  15618.     */
  15619.     IF EXISTS (SELECT * FROM syspublications WHERE name = @publication and snapshot_jobid <> NULL)
  15620.     BEGIN
  15621.         RAISERROR (14101, 11, -1, @publication)
  15622.         RETURN(1)
  15623.     END
  15624.  
  15625.     /* Get publication_type */
  15626.     SELECT @publication_type = repl_freq from syspublications WHERe name = @publication
  15627.     
  15628.     /*
  15629.     ** Get distributor information
  15630.     */
  15631.     EXEC @retcode = dbo.sp_helpdistributor @distributor = @distributor OUTPUT, 
  15632.         @distribdb = @distribdb OUTPUT,
  15633.         @rpcsrvname = @dist_rpcname OUTPUT
  15634.     IF @@error <> 0 OR @retcode <> 0 or @distributor IS NULL OR @distribdb IS NULL
  15635.     BEGIN
  15636.         RAISERROR (14071, 16, -1)
  15637.         RETURN (1)
  15638.     END
  15639.  
  15640.     SELECT @database = DB_NAME()
  15641.  
  15642.     SELECT @distproc = RTRIM(@dist_rpcname) + '.' + @distribdb + '.dbo.sp_MSadd_snapshot_agent'
  15643.     
  15644.     SELECT @agent_args = '-Publisher ' + QUOTENAME(@@SERVERNAME)
  15645.     SELECT @agent_args = @agent_args + ' -PublisherDB ' + QUOTENAME(@database)
  15646.     SELECT @agent_args = @agent_args + ' -Distributor ' + QUOTENAME(@distributor)
  15647.     SELECT @agent_args = @agent_args + ' -Publication ' + QUOTENAME(@publication)
  15648.  
  15649.     BEGIN TRAN
  15650.  
  15651.     EXECUTE @retcode = @distproc 
  15652.         @name = @snapshot_job_name,
  15653.         @publisher = @@SERVERNAME,
  15654.         @publisher_db = @database,
  15655.         @publication = @publication,  
  15656.         @publication_type = @publication_type,
  15657.         @local_job = 1,  
  15658.  
  15659.         @freqtype = @freqtype, 
  15660.         @freqinterval = @freqinterval, 
  15661.         @freqsubtype = @freqsubtype, 
  15662.         @freqsubinterval = @freqsubinterval, 
  15663.         @freqrelativeinterval = @freqrelativeinterval, 
  15664.         @freqrecurrencefactor = @freqrecurrencefactor, 
  15665.         @activestartdate = @activestartdate, 
  15666.         @activeenddate = @activeenddate, 
  15667.         @activestarttimeofday = @activestarttimeofday, 
  15668.         @activeendtimeofday =  @activeendtimeofday,
  15669.         @command = @agent_args,
  15670.         @snapshot_jobid = @snapshot_jobid OUTPUT,
  15671.         @job_existing = @job_existing
  15672.   
  15673.    IF @@ERROR <> 0 or @retcode <> 0
  15674.         GOTO UNDO
  15675.  
  15676.     -- Legacy, use non zero taskid to indicate agent already created at the distributor.
  15677.     UPDATE syspublications set snapshot_jobid =  @snapshot_jobid
  15678.         WHERE name =  @publication 
  15679.  
  15680.     IF @@ERROR <> 0 
  15681.         GOTO UNDO
  15682.  
  15683.     -- This is the output parameter to indicate agent created.
  15684.     SELECT  @newagentid = 1
  15685.  
  15686.     COMMIT TRAN
  15687.  
  15688.     return (0)  
  15689.     
  15690. UNDO:
  15691.     if @@TRANCOUNT = 1
  15692.         ROLLBACK TRAN
  15693.     else
  15694.         COMMIT TRAN
  15695.     return(1)
  15696. GO
  15697.  
  15698. EXEC dbo.sp_MS_marksystemobject sp_MSaddpub_snapshot
  15699. GO
  15700.  
  15701. dump tran master with no_log
  15702. GO
  15703.  
  15704. /*
  15705. ** SyncTran support procs
  15706. */
  15707.  
  15708. print ''
  15709. print 'Creating procedure sp_MSis_pk_col'
  15710. go
  15711. create proc sp_MSis_pk_col @source_table sysname, @colname sysname, @indid int
  15712. as
  15713. begin
  15714.  
  15715.     declare @indkey int
  15716.     select @indkey = 1
  15717.  
  15718.     while @indkey < 16 and index_col(@source_table, @indid, @indkey) is not null
  15719.     begin
  15720.         if index_col(@source_table, @indid, @indkey) = @colname
  15721.             return (1)
  15722.  
  15723.         select @indkey = @indkey + 1
  15724.     end
  15725.  
  15726.     return (0)
  15727. end
  15728. GO
  15729. EXEC dbo.sp_MS_marksystemobject sp_MSis_pk_col
  15730. GO
  15731.  
  15732. print ''
  15733. print 'Creating procedure sp_MSmark_proc_norepl'
  15734. go
  15735.  
  15736. create procedure sp_MSmark_proc_norepl
  15737.     @procname nvarchar(517)
  15738. as
  15739.     set nocount on
  15740.  
  15741.     -- CHECK PERMISSIONS (MUST BE DBO) --
  15742.     if not (is_member('db_owner')=1 or is_srvrolemember('sysadmin') = 1) 
  15743.     begin
  15744.         raiserror(20521,0,1)
  15745.         return 1
  15746.     end
  15747.  
  15748.     -- CHECK THE OBJECT NAME --
  15749.     if object_id(@procname, 'local') is null
  15750.     begin
  15751.         raiserror(20522,0,1,@procname)
  15752.         return 1
  15753.     end
  15754.  
  15755.     -- DO THE UPDATE --
  15756.     begin tran
  15757.     exec dbo.sp_replupdateschema @procname
  15758.     update sysobjects set replinfo = replinfo | 0x40
  15759.                         where id = object_id(@procname, 'local')
  15760.     exec dbo.sp_replupdateschema @procname
  15761.     commit tran
  15762.     return @@error 
  15763. go
  15764.  
  15765. EXEC dbo.sp_MS_marksystemobject sp_MSmark_proc_norepl
  15766. GO
  15767.  
  15768. create procedure sp_MSdrop_expired_subscription
  15769. AS
  15770. /*
  15771. ** This stored procedure is to periodically check the status of all the subscriptions 
  15772. ** of every merge publication. If any of them is out-of-date, i.e., has lost contact
  15773. ** with publisher for a certain length of time, we can declare the death of that replica
  15774. ** and cleanup their traces at the publisher side
  15775. */
  15776. declare @independent_agent  bit
  15777. declare @article            sysname
  15778. declare @publication        sysname
  15779. declare @pubid              int
  15780. declare @artid              int
  15781. declare @publisher          sysname
  15782. declare @subscriber         sysname
  15783. declare @subscriber_id      smallint
  15784. declare @subscriber_db      sysname
  15785. declare @publisher_db       sysname
  15786. declare @out_of_date        int
  15787. declare @distributor        sysname
  15788. declare @distribdb          sysname
  15789. declare @retention          int  -- in days         
  15790. declare @retcode            smallint
  15791. declare @distproc           nvarchar(255)
  15792. declare @localproc          nvarchar(255)
  15793. declare @msg                nvarchar(255)
  15794. declare @open_cursor        nvarchar(400)
  15795.  
  15796.     /*
  15797.     ** Security Check
  15798.     */
  15799. EXEC @retcode = dbo.sp_MSreplcheck_publish
  15800.     IF @@ERROR <> 0 or @retcode <> 0
  15801.         return (1)
  15802.  
  15803.     /*
  15804.     ** Get distribution server information for remote RPC call.
  15805.     */
  15806. EXECUTE @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  15807.      @distribdb   = @distribdb OUTPUT
  15808. IF @@ERROR <> 0 or @retcode <> 0
  15809.     BEGIN
  15810.         RAISERROR (20036, 16, -1)
  15811.         return (1)
  15812.     END
  15813.  
  15814.     
  15815. SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MShelp_subscription_status '
  15816. select @publisher = @@SERVERNAME
  15817. select @publisher_db = db_name()
  15818.  
  15819. declare PC CURSOR LOCAL FAST_FORWARD for select DISTINCT name, pubid, independent_agent, retention from syspublications p
  15820.     open PC
  15821.     fetch PC into @publication, @pubid, @independent_agent, @retention
  15822.     WHILE (@@fetch_status <> -1)
  15823.         BEGIN
  15824.             -- Don't do anything if the retention is zero, this means
  15825.             -- subscriptions to the publication will never expire
  15826.             IF @retention = 0
  15827.             BEGIN
  15828.                 GOTO ZERO_RETENTION
  15829.             END
  15830.             declare SC CURSOR LOCAL FAST_FORWARD for select s.srvid, s.dest_db, a.name from syssubscriptions s, sysextendedarticlesview a 
  15831.                 where a.pubid= @pubid and s.artid = a.artid and s.srvid<>-1 
  15832.                 for read only
  15833.             open SC
  15834.             fetch SC into @subscriber_id, @subscriber_db, @article
  15835.             WHILE (@@fetch_status <> -1)
  15836.                 BEGIN
  15837.                     select @subscriber=srvname from master..sysservers where srvid=@subscriber_id
  15838.                     exec @retcode = @distproc @publisher = @publisher, 
  15839.                                     @publisher_db = @publisher_db, 
  15840.                                     @publication = @publication, 
  15841.                                     @subscriber = @subscriber, 
  15842.                                     @subscriber_db = @subscriber_db,
  15843.                                     @retention = @retention,
  15844.                                     @out_of_date = @out_of_date OUTPUT,
  15845.                                     @independent_agent = @independent_agent
  15846.                     if @retcode<>0 or @@ERROR<>0 
  15847.                         begin
  15848.                             close SC
  15849.                             deallocate SC
  15850.                             close PC
  15851.                             deallocate PC
  15852.                             return (1)
  15853.                         end
  15854.                     IF (@out_of_date = 1)
  15855.                         begin
  15856.                             exec @retcode = dbo.sp_dropsubscription   -- publisher_db.dbo.sp_dropsubscription
  15857.                                 @publication = @publication,
  15858.                                 @article = @article,
  15859.                                 @subscriber = @subscriber,
  15860.                                 @destination_db = @subscriber_db,
  15861.                                 @reserved = 'internal'
  15862.                             if @retcode <>0 or @@ERROR<>0
  15863.                                 begin
  15864.                                     close SC
  15865.                                     deallocate SC
  15866.                                     close PC
  15867.                                     deallocate PC
  15868.                                     return (1)
  15869.                                 end
  15870.                             raiserror(14157, 10, -1, @subscriber, @publication) 
  15871.                         end
  15872.                     fetch SC into @subscriber_id, @subscriber_db, @article
  15873.                 END
  15874.             CLOSE SC
  15875.             DEALLOCATE SC
  15876.     ZERO_RETENTION:
  15877.             fetch PC into @publication, @pubid, @independent_agent, @retention
  15878.         END
  15879.     CLOSE PC
  15880.     DEALLOCATE PC
  15881.  
  15882. GO
  15883. EXEC dbo.sp_MS_marksystemobject sp_MSdrop_expired_subscription
  15884. go
  15885.  
  15886.  
  15887. -- synctran supporting procs
  15888. raiserror('Creating procedure sp_MSscript_validate_subscription', 0,1)
  15889. go
  15890. create procedure sp_MSscript_validate_subscription (
  15891.     @publication sysname,
  15892.     @article sysname)
  15893. as
  15894. BEGIN
  15895.     declare @cmd          nvarchar(4000)
  15896.     declare @pubid int
  15897.     declare @artid int
  15898.     select @pubid = pubid from syspublications where name = @publication
  15899.     select @artid = artid from sysarticles where pubid = @pubid and name = @article
  15900.  
  15901.     select @cmd = N'
  15902.     ' + N'--
  15903.     ' + N'-- Check for subscription validation
  15904.     ' + N'--
  15905.     exec @retcode = dbo.sp_MSvalidate_subscription @orig_server, @orig_db, '
  15906.             + convert(nvarchar(10), @artid) + N'
  15907.     if (@retcode != 0 or @@error != 0)
  15908.         return -1'
  15909.  
  15910.     insert into #proctext(procedure_text) values(@cmd)
  15911.     return 0        
  15912. END                    
  15913. go
  15914. EXEC dbo.sp_MS_marksystemobject sp_MSscript_validate_subscription
  15915. GO
  15916.  
  15917.  
  15918. -- synctran supporting procs
  15919. raiserror('Creating procedure sp_MSvalidate_subscription', 0,1)
  15920. go
  15921. create procedure sp_MSvalidate_subscription
  15922.     @subscriber sysname,
  15923.     @subscriber_db sysname,
  15924.     @artid int
  15925. as
  15926.  
  15927.     declare @srvid smallint
  15928.     select @srvid = srvid from master..sysservers where UPPER(srvname) = UPPER(@subscriber) collate database_default
  15929.     if not exists (select * from syssubscriptions where artid = @artid and 
  15930.         srvid = @srvid and dest_db = @subscriber_db)
  15931.     begin
  15932.         --  The subscription has been dropped from the publisher. Please run sp_subscription_cleanup to cleanup the triggers.
  15933.         exec sp_MSreplraiserror 21161
  15934.         return -1
  15935.     end                    
  15936. go
  15937. EXEC dbo.sp_MS_marksystemobject sp_MSvalidate_subscription
  15938. GO
  15939.  
  15940.  
  15941. raiserror('Creating procedure sp_MSscript_insert_statement', 0,1)
  15942. go
  15943. create procedure sp_MSscript_insert_statement(
  15944.     @objid int,
  15945.     @columns binary(32),
  15946.     @identity_insert bit = 0,
  15947.     @queued_pub bit = 0
  15948.     )
  15949. as
  15950. BEGIN
  15951.     declare @cmd          nvarchar(4000)
  15952.     declare @qualname     nvarchar(512)
  15953.     declare @colname      sysname
  15954.     declare @ccoltype     sysname
  15955.     declare @this_col     int
  15956.     declare @rc           int
  15957.     declare @num_col      int
  15958.     declare @column_string nvarchar(4000)
  15959.             ,@var_string nvarchar(4000)
  15960.     
  15961.     
  15962.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  15963.  
  15964.     --
  15965.     -- start scripting
  15966.     --
  15967.     select @cmd = N'
  15968.     ' + N'--
  15969.     ' + N'-- detection/conflict resolution stage
  15970.     ' + N'--'
  15971.     
  15972.     if (@queued_pub = 1)
  15973.     begin
  15974.         select @cmd = @cmd + N'
  15975.     if (@execution_mode = @QPubWins)
  15976.         save tran cftpass'
  15977.     end
  15978.     insert into #proctext(procedure_text) values( @cmd) 
  15979.     
  15980.     --
  15981.     -- set indentity_insert on
  15982.     --
  15983.     if @identity_insert = 1
  15984.     begin
  15985.         -- Only to call set if identity is not marked for 'not for repl'
  15986.         -- This is to avoid security failure of 'SET' for PAL users
  15987.         if not exists (select * from syscolumns where id = @objid and
  15988.             ColumnProperty(id, name, 'IsIdNotForRepl') = 1)
  15989.         begin
  15990.             select @cmd = N'
  15991.     set identity_insert ' + @qualname + ' on'
  15992.             insert into #proctext(procedure_text) values( @cmd )
  15993.         end
  15994.     end
  15995.  
  15996.     --
  15997.     -- prepare the insert statement now
  15998.     --
  15999.     select @cmd = N'
  16000.     insert into ' + @qualname + N'( '
  16001.     insert into #proctext(procedure_text) values( @cmd )
  16002.     -- Generate strings for col names and variables
  16003.     select @num_col = 0
  16004.     select @cmd = N''
  16005.  
  16006.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  16007.     select colid from syscolumns where id = @objid order by colid asc
  16008.  
  16009.     OPEN hCColid
  16010.  
  16011.     FETCH hCColid INTO @this_col
  16012.  
  16013.     WHILE (@@fetch_status != -1)
  16014.     begin
  16015.         exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output
  16016.         if @rc = 0  and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  16017.         begin
  16018.             if rtrim(@ccoltype) not like N'timestamp' and 
  16019.                 not (ColumnProperty(@objid, @colname, 'IsIdentity') = 1 and 
  16020.                     @identity_insert = 0)
  16021.             begin
  16022.                 select @num_col = @num_col + 1
  16023.                 if @num_col > 1
  16024.                     select @cmd = @cmd + N', '
  16025.                 select @cmd = @cmd + QUOTENAME(@colname)            
  16026.                 exec dbo.sp_MSflush_command @cmd output, 1
  16027.             end
  16028.         end
  16029.         FETCH hCColid INTO @this_col
  16030.     end
  16031.     CLOSE hCColid
  16032.  
  16033.     -- Script end of colmn names
  16034.     select @cmd = N' )'
  16035.     insert into #proctext(procedure_text) values( @cmd )
  16036.  
  16037.     
  16038.     -- Script column value string
  16039.     if @num_col > 0
  16040.     begin
  16041.         select @cmd = N'
  16042.     values ( '
  16043.         insert into #proctext(procedure_text) values( @cmd )
  16044.         -- Script column value string
  16045.         select @num_col = 0
  16046.         select @cmd = N''
  16047.  
  16048.         OPEN hCColid
  16049.  
  16050.         FETCH hCColid INTO @this_col
  16051.  
  16052.         WHILE (@@fetch_status != -1)
  16053.         begin
  16054.             exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output
  16055.             if @rc = 0  and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  16056.             begin
  16057.                 if rtrim(@ccoltype) not like N'timestamp' and 
  16058.                     not (ColumnProperty(@objid, @colname, 'IsIdentity') = 1 and 
  16059.                         @identity_insert = 0)
  16060.                 begin
  16061.                     select @num_col = @num_col + 1
  16062.                     if @num_col > 1
  16063.                         select @cmd = @cmd + N', '
  16064.                     select @cmd = @cmd + N'@c' + cast(@this_col as nvarchar(4))                
  16065.                     exec dbo.sp_MSflush_command @cmd output, 1
  16066.                 end
  16067.             end
  16068.             FETCH hCColid INTO @this_col
  16069.         end
  16070.         CLOSE hCColid
  16071.         
  16072.         -- Script end of column value string
  16073.         select @cmd = N' )
  16074.     '
  16075.         insert into #proctext(procedure_text) values( @cmd )
  16076.     end
  16077.     else
  16078.     begin
  16079.         -- This is to set @@rowcount.
  16080.         insert into #proctext(procedure_text) values( N' 
  16081.     select @retcode = @retcode')
  16082.     end
  16083.     
  16084.     --
  16085.     -- set the rowcount and error
  16086.     --
  16087.     select @cmd = N'
  16088.     select @rowcount = @@ROWCOUNT, @error = @@ERROR 
  16089.     '
  16090.     insert into #proctext(procedure_text) values( @cmd )
  16091.  
  16092.     --
  16093.     -- set indentity_insert off
  16094.     --
  16095.     if @identity_insert = 1
  16096.     begin
  16097.         -- Only to call set if identity is not marked for 'not for repl'
  16098.         -- This is to avoid security failure of 'SET' for PAL users
  16099.         if not exists (select * from syscolumns where id = @objid and
  16100.             ColumnProperty(id, name, 'IsIdNotForRepl') = 1)
  16101.         begin
  16102.             select @cmd = N'
  16103.     set identity_insert ' + @qualname + ' off'
  16104.             insert into #proctext(procedure_text) values( @cmd )
  16105.         end
  16106.     end
  16107.  
  16108.  
  16109.     if (@queued_pub = 1)
  16110.     begin
  16111.         select @cmd = N'
  16112.     if (@execution_mode = @QPubWins)
  16113.         rollback tran cftpass'
  16114.         insert into #proctext(procedure_text) values( @cmd )
  16115.     end
  16116.     
  16117.     --
  16118.     -- all done 
  16119.     -- 
  16120.     return 0
  16121. END
  16122. go
  16123.  
  16124. EXEC dbo.sp_MS_marksystemobject sp_MSscript_insert_statement
  16125. GO
  16126.  
  16127. --
  16128. -- proc to generate subscriber wins resolution code block
  16129. -- for insert proc used for synctran/queued
  16130. --
  16131. raiserror('Creating procedure sp_MSscript_insert_subwins', 0,1)
  16132. go
  16133. create procedure sp_MSscript_insert_subwins (
  16134.     @publication sysname,
  16135.     @article     sysname, 
  16136.     @objid int,
  16137.     @columns binary(32),
  16138.     @identity_insert bit)
  16139. AS
  16140. BEGIN
  16141.     declare @cmd nvarchar(4000)
  16142.             ,@qualname nvarchar(512)
  16143.             ,@column_string nvarchar(4000)
  16144.             ,@var_string nvarchar(4000)
  16145.             ,@colname      sysname
  16146.             ,@ccoltype     sysname
  16147.             ,@this_col     int
  16148.             ,@rc           int
  16149.             ,@num_col      int
  16150.  
  16151.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  16152.  
  16153.     select @cmd = N'
  16154.     if (@error in (0, 547, 2627) and @execution_mode = @QSubWins)
  16155.     begin
  16156.         ' + N'--
  16157.         ' + N'-- Subscriber Wins resolution
  16158.         ' + N'--
  16159.         if (@rowcount = 1 and @error = 0)
  16160.         begin'
  16161.  
  16162.     insert into #proctext(procedure_text) values( @cmd )
  16163.  
  16164.     select @cmd = N'
  16165.             ' + N'--
  16166.             ' + N'-- No conflict for this command
  16167.             ' + N'-- do nothing
  16168.             ' + N'-- will remove this code block later 
  16169.             ' + N'-- for optimization
  16170.             ' + N'--
  16171.             select @retcode = 0
  16172.         end'
  16173.  
  16174.     insert into #proctext(procedure_text) values( @cmd )
  16175.  
  16176.     select @cmd = N'        
  16177.         else if (@rowcount = 0 and @error in (547, 2627))
  16178.         begin
  16179.             ' + N'--
  16180.             ' + N'-- Conflict for this command
  16181.             ' + N'-- Row already exists
  16182.             ' + N'-- delete and insert row with Queue values
  16183.             ' + N'-- '
  16184.     insert into #proctext(procedure_text) values( @cmd )
  16185.  
  16186.     --
  16187.     -- script delete
  16188.     --
  16189.     select @cmd = N'
  16190.             delete ' + @qualname 
  16191.     insert into #proctext(procedure_text) values( @cmd )
  16192.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0
  16193.  
  16194.     --
  16195.     -- script the insert assignment
  16196.     --
  16197.     select @num_col = 0
  16198.     create table #worktab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  16199.     create table #worktab2 ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  16200.  
  16201.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  16202.     select colid from syscolumns where id = @objid order by colid asc
  16203.  
  16204.     OPEN hCColid
  16205.     FETCH hCColid INTO @this_col
  16206.     WHILE (@@fetch_status != -1)
  16207.     begin
  16208.         exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output
  16209.         if @rc = 0  and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  16210.         begin
  16211.             if rtrim(@ccoltype) not like N'timestamp' 
  16212.             begin
  16213.                 select @num_col = @num_col + 1
  16214.                 select @column_string = QUOTENAME(@colname)
  16215.                 select @var_string = N'@c' + cast(@this_col as nvarchar(4))
  16216.                 
  16217.                 if (@num_col > 1)
  16218.                 begin
  16219.                     select @column_string = N', ' + @column_string
  16220.                     select @var_string = N', ' +@var_string 
  16221.                 end
  16222.  
  16223.                 insert into #worktab(procedure_text) values( @column_string )                
  16224.                 insert into #worktab2(procedure_text) values( @var_string )                
  16225.                 
  16226.             end
  16227.         end
  16228.         FETCH hCColid INTO @this_col
  16229.     end
  16230.     CLOSE hCColid
  16231.     DEALLOCATE hCColid
  16232.  
  16233.     if (@num_col > 0)
  16234.     begin
  16235.         if (@identity_insert = 1)
  16236.         begin
  16237.             -- Only to call set if identity is not marked for 'not for repl'
  16238.             -- This is to avoid security failure of 'SET' for PAL users
  16239.             if not exists (select * from syscolumns where id = @objid and
  16240.                 ColumnProperty(id, name, 'IsIdNotForRepl') = 1)
  16241.             begin
  16242.                 select @cmd = N'
  16243.             set identity_insert ' + @qualname + N' on '
  16244.                 insert into #proctext(procedure_text) values( @cmd )
  16245.             end
  16246.         end
  16247.  
  16248.         select @cmd = N'
  16249.             insert into ' + @qualname + N'( '
  16250.         insert into #proctext(procedure_text) values( @cmd )
  16251.         insert into #proctext(procedure_text) 
  16252.             select procedure_text from #worktab order by c1 asc
  16253.         select @cmd = N' )
  16254.             values ( '
  16255.         insert into #proctext(procedure_text) values( @cmd )
  16256.         insert into #proctext(procedure_text) 
  16257.             select procedure_text from #worktab2 order by c1 asc
  16258.         select @cmd = N' )'
  16259.         insert into #proctext(procedure_text) values( @cmd )
  16260.  
  16261.         if (@identity_insert = 1)
  16262.         begin
  16263.             -- Only to call set if identity is not marked for 'not for repl'
  16264.             -- This is to avoid security failure of 'SET' for PAL users
  16265.             if not exists (select * from syscolumns where id = @objid and
  16266.                 ColumnProperty(id, name, 'IsIdNotForRepl') = 1)
  16267.             begin
  16268.                 select @cmd = N'
  16269.             set identity_insert ' + @qualname + N' off '
  16270.                 insert into #proctext(procedure_text) values( @cmd )
  16271.             end
  16272.         end
  16273.     end
  16274.     
  16275.     select @cmd = N'
  16276.             if (@@error != 0 or @retcode != 0)
  16277.                 return -1
  16278.         end
  16279.         else
  16280.             return -1
  16281.     end'
  16282.     insert into #proctext(procedure_text) values( @cmd )
  16283.  
  16284.     --
  16285.     -- all done
  16286.     --
  16287.     drop table #worktab
  16288.     drop table #worktab2
  16289.     return 0
  16290. END
  16291. go
  16292.  
  16293. EXEC dbo.sp_MS_marksystemobject sp_MSscript_insert_subwins
  16294. GO
  16295.  
  16296. --
  16297. -- proc to test if we need to turn on identity insert
  16298. --
  16299. raiserror('Creating procedure sp_MSis_identity_insert', 0,1)
  16300. go
  16301. create procedure sp_MSis_identity_insert
  16302. @publication sysname,
  16303. @article sysname,
  16304. @identity_insert bit output,
  16305. @artid int = NULL    -- If pass in @artid, you don't need to pass in 
  16306.                     -- @publication and @article
  16307. as
  16308.     declare @pubid int, @source_objid int
  16309.         ,@columns      binary(32)
  16310.     
  16311.     select @identity_insert = 0
  16312.  
  16313.     -- Get @artid if not there
  16314.     -- If the publication is not queued
  16315.     if @artid is null
  16316.     begin
  16317.         select @pubid = pubid from syspublications where name = @publication
  16318.         select @artid = artid from sysarticles where
  16319.             pubid = @pubid and
  16320.             name = @article
  16321.     end        
  16322.  
  16323.     -- Get @pubid from @artid
  16324.     if @pubid is null
  16325.         select @pubid = pubid    from sysarticles where 
  16326.             artid = @artid
  16327.  
  16328.     if exists (select * from syspublications where
  16329.         pubid = @pubid and
  16330.         allow_queued_tran = 1)
  16331.     begin
  16332.         select @source_objid = objid, @columns = columns from sysarticles where
  16333.             artid = @artid and
  16334.             OBJECTPROPERTY(objid, 'tablehasidentity') = 1
  16335.         if @source_objid is not null
  16336.         begin
  16337.             declare @colid smallint, @in_partition int
  16338.             select @colid = colid from syscolumns where id = @source_objid and
  16339.                 COLUMNPROPERTY(@source_objid, name, 'IsIdentity') = 1
  16340.             exec @in_partition = sp_isarticlecolbitset @colid, @columns
  16341.             if @in_partition = 1
  16342.                 select @identity_insert = 1
  16343.         end
  16344.     end
  16345.     return @identity_insert
  16346. go
  16347.  
  16348. EXEC dbo.sp_MS_marksystemobject sp_MSis_identity_insert
  16349. GO
  16350.  
  16351.  
  16352. /************* NOT used anymore - use DEL + INSERT compensation instead *******************
  16353. --
  16354. -- proc that generates a compensating update command string
  16355. -- specify the type of proc where this generation will be used
  16356. --
  16357. create procedure sp_MSscript_compensating_update (
  16358.     @publication sysname,
  16359.     @article     sysname, 
  16360.     @objid int,
  16361.     @columns binary(32),
  16362.     @proctype    int = 0)        -- 0 insert, 1 delete, 2 update
  16363. AS
  16364. BEGIN
  16365.     declare @cmd nvarchar(4000)
  16366.             ,@artid int
  16367.             ,@pubid int
  16368.             ,@dest_table sysname
  16369.             ,@colname      sysname
  16370.             ,@ccoltype     sysname
  16371.             ,@this_col     int
  16372.             ,@rc           int
  16373.             ,@num_col      int
  16374.             ,@qualname nvarchar(512)
  16375.             ,@cast_str nvarchar(1000)
  16376.             ,@column_string nvarchar(4000)
  16377.             ,@rowcnt int
  16378.             ,@setprefix bit
  16379.  
  16380.     --
  16381.     -- initialize the vars we will use
  16382.     --
  16383.     select @pubid = pubid from syspublications where name = @publication
  16384.     select @artid = artid, @dest_table = dest_table from sysarticles 
  16385.         where name = @article and pubid = @pubid
  16386.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  16387.  
  16388.     create table #outputtab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  16389.  
  16390.     --
  16391.     -- Generate the update compensation code
  16392.     -- We are generating a string assignment so it is 
  16393.     -- tricky about non string vars
  16394.     --
  16395.     select @num_col = 0
  16396.  
  16397.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  16398.     select colid from syscolumns where id = @objid order by colid asc
  16399.  
  16400.     OPEN hCColid
  16401.     FETCH hCColid INTO @this_col
  16402.     WHILE (@@fetch_status != -1)
  16403.     begin
  16404.         exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output
  16405.         if @rc = 0  and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  16406.         begin
  16407.             if rtrim(@ccoltype) not like N'timestamp' and ColumnProperty(@objid, @colname, 'IsIdentity') != 1
  16408.             begin
  16409.                 select @num_col = @num_col + 1
  16410.                 
  16411.                 if (lower(@ccoltype) in ('varchar','nvarchar'))
  16412.                     select @cast_str = N' = '' + ISNULL('''''''' + master.dbo.fn_MSgensqescstr(' + quotename(@colname) + N') collate database_default + '''''''', ''null'') + '
  16413.                 else if (lower(@ccoltype) in ('char','nchar'))
  16414.                     select @cast_str = N' = '' + ISNULL('''''''' + master.dbo.fn_MSgensqescstr(CAST(RTRIM(' + quotename(@colname) + N') as nvarchar)) collate database_default + '''''''', ''null'') + '
  16415.                 else if (lower(@ccoltype) in ('binary','varbinary'))
  16416.                     select @cast_str = N' = '' + ISNULL(master.dbo.fn_varbintohexstr(' + quotename(@colname) + N') collate database_default, ''null'') + '
  16417.                 else if (lower(@ccoltype) in ('bit','bigint','int','smallint','tinyint','float','real','decimal','numeric'))
  16418.                     select @cast_str = N' = '' + ISNULL(CAST(' + quotename(@colname) + N' as nvarchar), ''null'') + '
  16419.                 else if (lower(@ccoltype) in ('money','smallmoney'))
  16420.                     select @cast_str = N' = '' + ISNULL(CONVERT(nvarchar(40),' + quotename(@colname) + N',2), ''null'') + '
  16421.                 else if (lower(@ccoltype) = 'uniqueidentifier')
  16422.                     select @cast_str = N' = '' + ISNULL('''''''' + CAST(' + quotename(@colname) + N' as nvarchar(40)) + '''''''', ''null'') + '
  16423.                 else if (lower(@ccoltype) in ('datetime','smalldatetime'))
  16424.                     select @cast_str = N' = '' + ISNULL('''''''' + CONVERT(nvarchar(40), ' + quotename(@colname) + N', 121) + '''''''', ''null'') + '
  16425.                 else if (lower(@ccoltype) = 'sql_variant')
  16426.                     select @cast_str = N' = '' + ISNULL(master.dbo.fn_sqlvarbasetostr(' + quotename(@colname) + N' ) collate database_default, ''null'') + '
  16427.                 else
  16428.                     select @cast_str = N' = '' + ISNULL(CAST(' + quotename(@colname) + N' as nvarchar), ''null'') + '
  16429.                 
  16430.                 if (@num_col = 1)
  16431.                 begin
  16432.                     select @column_string = N'
  16433.                 ''' + quotename(@colname) + @cast_str
  16434.                 end
  16435.                 else
  16436.                 begin
  16437.                     select @column_string = N'
  16438.                 '',' + quotename(@colname) + @cast_str
  16439.                 end
  16440.  
  16441.                 --
  16442.                 -- save this output in the table
  16443.                 --
  16444.                 insert into #outputtab(procedure_text) values( @column_string )                                
  16445.             end
  16446.         end
  16447.         FETCH hCColid INTO @this_col
  16448.     end
  16449.     CLOSE hCColid
  16450.     DEALLOCATE hCColid
  16451.     
  16452.     select @cmd = N'            
  16453.             select @cmd = ''UPDATE ' + quotename(@dest_table) + N' SET '' + ' 
  16454.     insert into #proctext(procedure_text) values( @cmd )
  16455.  
  16456.     select @rowcnt = 1, @setprefix = 1
  16457.     declare #htempcur cursor local for
  16458.         select procedure_text from #outputtab order by c1 asc
  16459.     for read only
  16460.  
  16461.     open #htempcur
  16462.     fetch #htempcur into @column_string
  16463.     while (@@fetch_status = 0)
  16464.     begin
  16465.         insert into #proctext(procedure_text) select @column_string
  16466.         select @rowcnt = @rowcnt + 1
  16467.  
  16468.         --
  16469.         -- if we have processed 10 terms then split the command
  16470.         --
  16471.         if (@rowcnt > 9)
  16472.         begin
  16473.             select @cmd = N''' ''
  16474.             from ' + @qualname 
  16475.             insert into #proctext(procedure_text) values( @cmd )
  16476.  
  16477.             if (@proctype = 0)
  16478.                 exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0, 'ins'
  16479.             else if (@proctype = 2)
  16480.                 exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0, 'upd'
  16481.     
  16482.             exec sp_MSscript_compensating_send @pubid, @artid, 1, @setprefix
  16483.  
  16484.             select @cmd = N'
  16485.             select @cmd = ' 
  16486.             insert into #proctext(procedure_text) values( @cmd )
  16487.             select @rowcnt = 0, @setprefix = 0
  16488.         end
  16489.         fetch #htempcur into @column_string
  16490.     end
  16491.  
  16492.     close #htempcur
  16493.     deallocate #htempcur
  16494.     
  16495.     --
  16496.     -- script the where for the compensating command
  16497.     --
  16498.     if (@proctype = 0)
  16499.         exec dbo.sp_MSscript_where_clause @objid, @columns, 'qcft_comp', NULL, 0, 'ins'
  16500.     else if (@proctype = 2)
  16501.         exec dbo.sp_MSscript_where_clause @objid, @columns, 'qcft_comp', NULL, 0, 'upd'
  16502.  
  16503.     select @cmd = N'
  16504.             from ' + @qualname 
  16505.     insert into #proctext(procedure_text) values( @cmd )
  16506.  
  16507.     if (@proctype = 0)
  16508.         exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0, 'ins'
  16509.     else if (@proctype = 2)
  16510.         exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0, 'upd'
  16511.  
  16512.     exec sp_MSscript_compensating_send @pubid, @artid, 0, @setprefix
  16513.     
  16514.     --
  16515.     -- all done
  16516.     --
  16517.     drop table #outputtab
  16518.     return 0
  16519. END
  16520. **************************************************************************************************/
  16521. go
  16522.  
  16523. --
  16524. -- proc that scripts the sending of a compensating command
  16525. -- used by the compensating code generation SPs
  16526. --
  16527. raiserror('Creating procedure sp_MSscript_compensating_send', 0,1)
  16528. go
  16529. create procedure sp_MSscript_compensating_send (
  16530.     @pubid int,
  16531.     @artid int,
  16532.     @cmdstate int = 0,
  16533.     @setprefix bit = 1)
  16534. AS
  16535. BEGIN
  16536.     declare @cmd nvarchar(4000)
  16537.     
  16538.     select @cmd = N'
  16539.             ' + N'--
  16540.             ' + N'-- sending of compensating command
  16541.             ' + N'--'
  16542.     insert into #proctext(procedure_text) values( @cmd )
  16543.  
  16544.     select @cmd = N'
  16545.             exec @retcode = dbo.sp_MSadd_compensating_cmd
  16546.                 @orig_srv = @orig_server
  16547.                 ,@orig_db = @orig_db
  16548.                 ,@command = @cmd
  16549.                 ,@article_id = ' + CAST(@artid as nvarchar(4)) + N'
  16550.                 ,@publication_id = ' + CAST(@pubid as nvarchar(4)) + N'
  16551.                 ,@cmdstate = ' + CAST(@cmdstate as nvarchar(4)) + N'
  16552.                 ,@mode = 0
  16553.                 ,@setprefix = ' + CAST(@setprefix as nvarchar(4))
  16554.     insert into #proctext(procedure_text) values( @cmd )
  16555.  
  16556.     select @cmd = N'
  16557.             if (@@error != 0 or @retcode != 0)
  16558.                 return -1'
  16559.     insert into #proctext(procedure_text) values( @cmd )
  16560.  
  16561.     --
  16562.     -- all done
  16563.     --
  16564.     return 0    
  16565. END
  16566. go
  16567.  
  16568. EXEC dbo.sp_MS_marksystemobject sp_MSscript_compensating_send
  16569. GO
  16570.  
  16571. --
  16572. -- proc to generate publisher wins resolution code block
  16573. -- for insert proc used for synctran/queued
  16574. --
  16575. raiserror('Creating procedure sp_MSscript_insert_pubwins', 0,1)
  16576. go
  16577. create procedure sp_MSscript_insert_pubwins (
  16578.     @publication sysname,
  16579.     @article     sysname, 
  16580.     @objid int,
  16581.     @columns binary(32) )
  16582. AS
  16583. BEGIN
  16584.     declare @cmd nvarchar(4000)
  16585.             ,@artid int
  16586.             ,@pubid int
  16587.             ,@dest_table sysname
  16588.             ,@dest_owner sysname
  16589.             ,@colname      sysname
  16590.             ,@ccoltype     sysname
  16591.             ,@this_col     int
  16592.             ,@rc           int
  16593.             ,@num_col      int
  16594.             ,@qualname nvarchar(512)
  16595.             ,@cast_str nvarchar(1000)
  16596.             ,@decl_str nvarchar(2000)
  16597.             ,@assign_str nvarchar(4000)
  16598.             ,@typestring nvarchar(100)
  16599.             ,@exec_str nvarchar(1000)
  16600.  
  16601.     --
  16602.     -- initialize the vars we will use
  16603.     --
  16604.     select @pubid = pubid from syspublications where name = @publication
  16605.     select @artid = artid, @dest_table = dest_table, @dest_owner = dest_owner
  16606.     from sysarticles where name = @article and pubid = @pubid
  16607.     select @dest_owner = case when (@dest_owner IS NULL) then N''
  16608.                 else quotename(@dest_owner) + N'.' end
  16609.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  16610.                 
  16611.     --
  16612.     -- start script generation
  16613.     --
  16614.     select @cmd = N'
  16615.     else if (@error in (0, 547, 2627) and @execution_mode = @QPubWins)
  16616.     begin
  16617.         ' + N'--
  16618.         ' + N'-- Publisher Wins resolution
  16619.         ' + N'-- Find where we have to generate compensating action
  16620.         ' + N'--
  16621.         if (@rowcount = 1 and @error = 0)
  16622.         begin'
  16623.     insert into #proctext(procedure_text) values( @cmd )
  16624.  
  16625.     select @cmd = N'
  16626.             ' + N'--
  16627.             ' + N'-- No conflict for this command
  16628.             ' + N'-- Row does not exist
  16629.             ' + N'-- Generate delete compensating action
  16630.             ' + N'--
  16631.             select @cftcase = 23'
  16632.     insert into #proctext(procedure_text) values( @cmd )
  16633.  
  16634.     --
  16635.     -- Continue with scripting
  16636.     --
  16637.     select @cmd = N'
  16638.         end
  16639.         else if (@rowcount = 0 and @error in (547, 2627))
  16640.         begin
  16641.             ' + N'--
  16642.             ' + N'-- conflict for this command
  16643.             ' + N'-- Row already exists
  16644.             ' + N'-- generate update compensating action
  16645.             ' + N'-- DELETE compensating command + INSERT compensating command
  16646.             ' + N'--            
  16647.             select @cftcase = 21'
  16648.     insert into #proctext(procedure_text) values( @cmd )
  16649.  
  16650.     --
  16651.     -- continue with scripting
  16652.     --            
  16653.     select @cmd = N'        
  16654.         end
  16655.         else
  16656.             return -1
  16657.  
  16658.         ' + N'--
  16659.         ' + N'-- generate compensating command according to the cases
  16660.         ' + N'--'
  16661.     insert into #proctext(procedure_text) values( @cmd )
  16662.  
  16663.     select @cmd = N'
  16664.         if (@cftcase in (21,23))
  16665.         begin
  16666.             ' + N'--
  16667.             ' + N'-- delete compensating command
  16668.             ' + N'--'
  16669.     insert into #proctext(procedure_text) values( @cmd )
  16670.     
  16671.     --
  16672.     -- Generate the delete compensating code
  16673.     --
  16674.     select @cmd = N'
  16675.             select @cmd = ''DELETE ' + @dest_owner + quotename(@dest_table) + N' '' + '
  16676.     insert into #proctext(procedure_text) values( @cmd )
  16677.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'qcft_comp', NULL, 0, 'ins'
  16678.     exec sp_MSscript_compensating_send @pubid, @artid, 0, 1
  16679.  
  16680.     select @cmd = N'
  16681.         end
  16682.  
  16683.         if (@cftcase = 21)
  16684.         begin
  16685.             ' + N'--
  16686.             ' + N'-- insert compensating command
  16687.             ' + N'--'
  16688.  
  16689.     --
  16690.     -- generate the compensating insert command
  16691.     --
  16692.     exec dbo.sp_MSscript_compensating_insert @publication, @article, @objid, @columns, 0
  16693.  
  16694.     --
  16695.     -- continue with scripting
  16696.     --            
  16697.     select @cmd = N'        
  16698.         end
  16699.     end'
  16700.     insert into #proctext(procedure_text) values( @cmd )
  16701.  
  16702.     --
  16703.     -- all done
  16704.     --
  16705.     return 0    
  16706. END
  16707. go
  16708.  
  16709. EXEC dbo.sp_MS_marksystemobject sp_MSscript_insert_pubwins
  16710. GO
  16711.  
  16712.  
  16713.  
  16714. raiserror('Creating procedure sp_MSscript_update_statement', 0,1)
  16715. go
  16716. create procedure sp_MSscript_update_statement (
  16717.     @publication sysname,
  16718.     @article     sysname, 
  16719.     @objid int,
  16720.     @columns binary(32),
  16721.     @queued_pub bit = 0
  16722. )
  16723. as
  16724. BEGIN
  16725.     declare @cmd            nvarchar(4000)
  16726.             ,@cmd2            nvarchar(4000)
  16727.             ,@qualname        nvarchar(512)
  16728.             ,@colname        sysname
  16729.             ,@typestring    nvarchar(4000)
  16730.             ,@spacer        nvarchar(1)
  16731.             ,@ccoltype        sysname
  16732.             ,@this_col        int
  16733.             ,@rc            int
  16734.             ,@column        nvarchar(4000)
  16735.             ,@num_col        int
  16736.  
  16737.             ,@art_col        int -- position in the article partition.
  16738.             ,@isset            int
  16739.             ,@timestamp_subscribed bit
  16740.             ,@pubid            int
  16741.  
  16742.     select @pubid = pubid from syspublications where name = @publication
  16743.  
  16744.     if exists (select * from sysarticles where pubid = @pubid and
  16745.         name = @article and
  16746.         status & 32 <> 0)
  16747.         select @timestamp_subscribed = 1
  16748.     else
  16749.         select @timestamp_subscribed = 0
  16750.     
  16751.     --
  16752.     -- Start scripting
  16753.     --
  16754.     select @cmd = N'
  16755.     ' + N'--
  16756.     ' + N'-- detection/conflict resolution stage
  16757.     ' + N'--'
  16758.     
  16759.     if (@queued_pub = 1)
  16760.     begin
  16761.         select @cmd = @cmd + N'
  16762.     if (@execution_mode = @QPubWins)
  16763.         save tran cftpass
  16764.     '
  16765.     end
  16766.     insert into #proctext(procedure_text) values(@cmd)
  16767.     
  16768.     --
  16769.     -- Generate the update statement
  16770.     --
  16771.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  16772.     select @cmd2 = N'
  16773.     update ' + @qualname + N' set
  16774.     '
  16775.  
  16776.     select @spacer = N' 
  16777.         '
  16778.     select @cmd = N''
  16779.     exec dbo.sp_MSpad_command @cmd output, 8
  16780.     
  16781.     select @num_col = 0
  16782.     select @art_col = 0
  16783.  
  16784.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  16785.     select colid from syscolumns where id = @objid order by colid asc
  16786.  
  16787.     OPEN hCColid
  16788.     FETCH hCColid INTO @this_col
  16789.     WHILE (@@fetch_status <> -1)
  16790.     begin
  16791.         -- Get the ordinal of the article partition or not.
  16792.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  16793.         if @isset = 0
  16794.         begin
  16795.             -- Special handling of a timestamp col in a queued tran publication
  16796.             -- See sp_helparticlecolumns : xtype 189 is timestamp
  16797.             if ((@timestamp_subscribed = 1) and 
  16798.                     exists ( select * from dbo.syscolumns where id = @objid and colid = @this_col and xtype = 189))
  16799.                 select @art_col = @art_col + 1
  16800.         end
  16801.         else
  16802.             select @art_col = @art_col + 1
  16803.  
  16804.         exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output
  16805.         if @rc = 0 and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  16806.         begin
  16807.             if rtrim(@ccoltype) not like N'timestamp' and ColumnProperty(@objid, @colname, 'IsIdentity') != 1
  16808.             begin
  16809.                 if @cmd2 is not null
  16810.                 begin
  16811.                     exec dbo.sp_MSflush_command @cmd2 output, 1, 8
  16812.                     select @cmd2 = null
  16813.                 end
  16814.  
  16815.                 select @num_col = @num_col + 1
  16816.                 -- Optimization:
  16817.                 -- Get null or actual column name
  16818.                 -- Note: the output is quoted.
  16819.                 exec dbo.sp_MSget_synctran_column 
  16820.                     @ts_col = null,
  16821.                     @op_type = null , -- 'ins, 'upd', 'del'
  16822.                     @is_new = null,
  16823.                     @primary_key_bitmap = null,
  16824.                     @colname = @colname,
  16825.                     @this_col = @this_col,
  16826.                     @column = @column output,
  16827.                     @from_proc = 1,
  16828.                     @art_col = @art_col -- position in the partition.
  16829.  
  16830.                 select @cmd = @cmd + @spacer + QUOTENAME(@colname) + N' = ' + @column                 
  16831.                 select @spacer = N','
  16832.  
  16833.                 --
  16834.                 -- flush command if necessary
  16835.                 --
  16836.                 exec dbo.sp_MSflush_command @cmd output, 1, 8
  16837.             end
  16838.         end
  16839.         FETCH hCColid INTO @this_col
  16840.     end
  16841.     CLOSE hCColid
  16842.     DEALLOCATE hCColid
  16843.  
  16844.     -- save off cmd fragment
  16845.     if @num_col > 0
  16846.     begin
  16847.         --
  16848.         -- Add the where clause based on the update mode
  16849.         --
  16850.         select @colname = 'msrepl_tran_version'
  16851.         exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', @colname, 4
  16852.     end 
  16853.     else
  16854.     -- set the @@rowcount
  16855.         insert into #proctext(procedure_text) values( N' select @retcode = @retcode
  16856.     ')
  16857.  
  16858.     --
  16859.     -- continue with rest of scripting
  16860.     --
  16861.     select @cmd = N'
  16862.     select @rowcount = @@ROWCOUNT, @error = @@ERROR
  16863.     '
  16864.  
  16865.     if (@queued_pub = 1)
  16866.     begin
  16867.         select @cmd = @cmd + N'
  16868.     if (@execution_mode = @QPubWins)
  16869.         rollback tran cftpass'
  16870.     end
  16871.     insert into #proctext(procedure_text) values(@cmd)
  16872.  
  16873.     --
  16874.     -- all done
  16875.     --
  16876.     return 0
  16877. END
  16878. go
  16879.  
  16880. EXEC dbo.sp_MS_marksystemobject sp_MSscript_update_statement
  16881. GO
  16882.  
  16883. --
  16884. -- proc to generate subscriber wins resolution code block
  16885. -- for update proc used for synctran/queued
  16886. --
  16887. raiserror('Creating procedure sp_MSscript_update_subwins', 0,1)
  16888. go
  16889. create procedure sp_MSscript_update_subwins (
  16890.     @publication sysname,
  16891.     @article     sysname, 
  16892.     @objid int,
  16893.     @columns binary(32),
  16894.     @identity_insert bit)
  16895. AS
  16896. BEGIN
  16897.     declare @cmd nvarchar(4000)
  16898.             ,@artid int
  16899.             ,@pubid int
  16900.             ,@qualname nvarchar(512)
  16901.             ,@column_string nvarchar(4000)
  16902.             ,@colname      sysname
  16903.             ,@ccoltype     sysname
  16904.             ,@this_col     int
  16905.             ,@rc           int
  16906.             ,@num_col      int
  16907.             ,@art_col      int
  16908.             ,@bitstr nvarchar(20)
  16909.             ,@bytestr nvarchar(20)
  16910.             ,@isset int
  16911.             ,@timestamp_subscribed bit
  16912.  
  16913.     --
  16914.     -- initialize the vars we will use
  16915.     --
  16916.     select @pubid = pubid from syspublications where name = @publication
  16917.     select @artid = artid from sysarticles 
  16918.         where name = @article and pubid = @pubid
  16919.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  16920.  
  16921.     --
  16922.     -- special flag for timestamp column subscription
  16923.     --
  16924.     if exists (select * from sysarticles where pubid = @pubid and
  16925.         name = @article and
  16926.         status & 32 <> 0)
  16927.         select @timestamp_subscribed = 1
  16928.     else
  16929.         select @timestamp_subscribed = 0
  16930.  
  16931.     --
  16932.     -- start scripting
  16933.     --
  16934.     select @cmd = N'
  16935.     if (@error in (0, 547, 2627) and @execution_mode = @QSubWins)
  16936.     begin
  16937.         ' + N'--
  16938.         ' + N'-- Subscriber Wins resolution
  16939.         ' + N'--
  16940.         select @retcode = 0
  16941.         if (@rowcount = 0)
  16942.         begin
  16943.             --
  16944.             -- Conflict for this command
  16945.             -- Check if PK update was being done
  16946.             --'
  16947.     insert into #proctext(procedure_text) values( @cmd )
  16948.     
  16949.     --
  16950.     -- script the PK update check
  16951.     --
  16952.     select @cmd = N'
  16953.             exec @retcode = dbo.sp_MSispkupdateinconflict ' + 
  16954.         cast(@pubid as nvarchar(10)) + N', ' + cast(@artid as nvarchar(10)) + N', @bitmap'
  16955.     insert into #proctext(procedure_text) values( @cmd )
  16956.  
  16957.     select @cmd = N'
  16958.             if (@retcode = -1)
  16959.                 return -1
  16960.             if (@retcode = 0)
  16961.             begin
  16962.                 ' + N'--
  16963.                 ' + N'-- PK update is not being done
  16964.                 ' + N'-- '
  16965.     insert into #proctext(procedure_text) values( @cmd )
  16966.  
  16967.     --
  16968.     -- script the if exists code using OLD_PK
  16969.     --
  16970.     select @cmd = N'
  16971.                 if exists (select * from ' + @qualname 
  16972.     insert into #proctext(procedure_text) values( @cmd )
  16973.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  16974.     insert into #proctext(procedure_text) values( N' )')
  16975.     
  16976.     --
  16977.     -- continue scripting
  16978.     --
  16979.     select @cmd = N'
  16980.                 begin
  16981.                     ' + N'--
  16982.                     ' + N'-- row with OLD_PK exists
  16983.                     ' + N'-- update row with OLD_PK with queue values
  16984.                     ' + N'-- 
  16985.                     select @cftcase = 11
  16986.                 end'
  16987.     insert into #proctext(procedure_text) values( @cmd )
  16988.  
  16989.     select @cmd = N'
  16990.                 else
  16991.                 begin
  16992.                     ' + N'--
  16993.                     ' + N'-- row with OLD_PK does not exists
  16994.                     ' + N'-- insert row with queue values using OLD_PK
  16995.                     ' + N'-- 
  16996.                     select @cftcase = 13
  16997.                 end
  16998.             end'
  16999.     insert into #proctext(procedure_text) values( @cmd )
  17000.  
  17001.     --
  17002.     -- continue scripting
  17003.     --
  17004.     select @cmd = N'
  17005.             else
  17006.             begin
  17007.                 ' + N'--
  17008.                 ' + N'-- PK update is being done
  17009.                 ' + N'-- drop rows with OLD_PK, NEW_PK and insert row with queue values
  17010.                 ' + N'--
  17011.                 select @cftcase = 0'
  17012.     insert into #proctext(procedure_text) values( @cmd )
  17013.                 
  17014.     --
  17015.     -- script the if exists code using OLD_PK
  17016.     --
  17017.     select @cmd = N'
  17018.                 if exists (select * from ' + @qualname 
  17019.     insert into #proctext(procedure_text) values( @cmd )
  17020.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  17021.     insert into #proctext(procedure_text) values( N' )')
  17022.     
  17023.     --
  17024.     -- continue scripting
  17025.     --
  17026.     select @cmd = N'
  17027.                 begin
  17028.                     ' + N'--
  17029.                     ' + N'-- row with OLD_PK exists
  17030.                     ' + N'-- insert row with queue values using NEW_PK +
  17031.                     ' + N'-- delete row with OLD_PK
  17032.                     ' + N'-- 
  17033.                     select @cftcase = 14
  17034.                 end' 
  17035.     insert into #proctext(procedure_text) values( @cmd )
  17036.     
  17037.     --
  17038.     -- script the if exists code using NEW_PK
  17039.     --
  17040.     select @cmd = N'
  17041.                 if exists (select * from ' + @qualname 
  17042.     insert into #proctext(procedure_text) values( @cmd )
  17043.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0
  17044.     insert into #proctext(procedure_text) values( N' )')
  17045.  
  17046.     --
  17047.     -- continue scripting
  17048.     --
  17049.     select @cmd = N'
  17050.                 begin
  17051.                     ' + N'--
  17052.                     ' + N'-- row with NEW_PK exists
  17053.                     ' + N'-- case 15: rows with NEW_PK and OLD_PK exist
  17054.                     ' + N'-- update row with NEW_PK with queue values + 
  17055.                     ' + N'-- delete row with OLD_PK'
  17056.     insert into #proctext(procedure_text) values( @cmd )
  17057.  
  17058.     select @cmd = N'
  17059.                     ' + N'-- case 16: row with NEW_PK exists
  17060.                     ' + N'-- update row with NEW_PK with queue values
  17061.                     ' + N'--
  17062.                     select @cftcase = case when (@cftcase = 14) then 15 else 16 end
  17063.                 end'
  17064.     insert into #proctext(procedure_text) values( @cmd )
  17065.  
  17066.     select @cmd = N'
  17067.                 if (@cftcase = 0)
  17068.                 begin
  17069.                     ' + N'--
  17070.                     ' + N'-- no existing rows with OLD_PK or NEW_PK
  17071.                     ' + N'-- insert with queue values
  17072.                     ' + N'--
  17073.                     select @cftcase = 12
  17074.                 end
  17075.             end'
  17076.     insert into #proctext(procedure_text) values( @cmd )
  17077.  
  17078.     --
  17079.     -- continue scripting
  17080.     --
  17081.     select @cmd = N'
  17082.             ' + N'--
  17083.             ' + N'-- based on retcode do the resolution
  17084.             ' + N'-- 
  17085.             if (@cftcase in (12, 13, 14))
  17086.             begin
  17087.                 ' + N'--
  17088.                 ' + N'-- insert
  17089.                 ' + N'--'
  17090.     insert into #proctext(procedure_text) values( @cmd )
  17091.  
  17092.     --
  17093.     -- prepare the insert statement
  17094.     --
  17095.     if (@identity_insert = 1)
  17096.     begin
  17097.         -- Only to call set if identity is not marked for 'not for repl'
  17098.         -- This is to avoid security failure of 'SET' for PAL users
  17099.         if not exists (select * from syscolumns where id = @objid and
  17100.             ColumnProperty(id, name, 'IsIdNotForRepl') = 1)
  17101.         begin
  17102.             select @cmd = N'
  17103.                 set identity_insert ' + @qualname + N' on '
  17104.             insert into #proctext(procedure_text) values( @cmd )
  17105.         end
  17106.     end
  17107.  
  17108.     select @cmd = N'
  17109.                 insert into ' + @qualname + N'('
  17110.     insert into #proctext(procedure_text) values( @cmd )
  17111.  
  17112.     select @num_col = 0
  17113.             ,@art_col = 0
  17114.             ,@cmd = NULL
  17115.     create table #collisttab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  17116.     create table #worktab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  17117.     
  17118.  
  17119.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  17120.     select colid from dbo.syscolumns where id = @objid order by colid asc
  17121.  
  17122.     OPEN hCColid
  17123.     FETCH hCColid INTO @this_col
  17124.     WHILE (@@fetch_status != -1)
  17125.     begin
  17126.         -- Get the ordinal of the article partition or not.
  17127.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  17128.         if @isset = 0
  17129.         begin
  17130.             if ((@timestamp_subscribed = 1) and 
  17131.                     exists ( select * from dbo.syscolumns where id = @objid and colid = @this_col and xtype = 189))
  17132.                 select @art_col = @art_col + 1
  17133.         end
  17134.         else
  17135.             select @art_col = @art_col + 1
  17136.  
  17137.         exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output
  17138.         if @rc = 0 and EXISTS (select name from dbo.syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  17139.         begin
  17140.             if rtrim(@ccoltype) != N'timestamp' 
  17141.             begin
  17142.                 select @num_col = @num_col + 1
  17143.                         ,@bytestr = cast((1 + (@art_col-1) / 8 ) as nvarchar)
  17144.                         ,@bitstr =  cast( power(2, (@art_col-1) % 8 ) as nvarchar)
  17145.  
  17146.                 select @column_string = N'case substring(@bitmap,' + 
  17147.                     @bytestr + N',1) & ' + @bitstr + N' when ' + @bitstr + 
  17148.                     N' then @c' + cast(@this_col as nvarchar(4)) + 
  17149.                     N' else @c' + cast(@this_col as nvarchar(4)) + N'_old end '
  17150.  
  17151.                 if (@num_col = 1)
  17152.                 begin
  17153.                     select @cmd = quotename(@colname)
  17154.                     select @column_string = N'
  17155.                     ' + @column_string
  17156.                 end
  17157.                 else
  17158.                 begin
  17159.                     select @cmd = @cmd + N',' + quotename(@colname)
  17160.                     select @column_string = N'
  17161.                     , ' + @column_string
  17162.                 end
  17163.  
  17164.                 -- transfer the column list string to table if large
  17165.                 if (len(@cmd) > 3000)
  17166.                 begin
  17167.                     insert into #collisttab(procedure_text) values( @cmd )
  17168.                     select @cmd = N' '
  17169.                 end
  17170.                 insert into #worktab(procedure_text) values( @column_string )
  17171.                 
  17172.             end
  17173.         end
  17174.         FETCH hCColid INTO @this_col
  17175.     end
  17176.     CLOSE hCColid
  17177.     DEALLOCATE hCColid
  17178.  
  17179.     -- transfer the remaining column list string to table
  17180.     insert into #collisttab(procedure_text) values( @cmd )
  17181.     
  17182.     insert into #proctext(procedure_text) 
  17183.         select procedure_text from #collisttab order by c1 asc
  17184.     select @cmd = N')
  17185.                 select '
  17186.     insert into #proctext(procedure_text) values( @cmd )
  17187.     insert into #proctext(procedure_text) 
  17188.         select procedure_text from #worktab order by c1 asc
  17189.  
  17190.     if (@identity_insert = 1)
  17191.     begin
  17192.         -- Only to call set if identity is not marked for 'not for repl'
  17193.         -- This is to avoid security failure of 'SET' for PAL users
  17194.         if not exists (select * from syscolumns where id = @objid and
  17195.             ColumnProperty(id, name, 'IsIdNotForRepl') = 1)
  17196.         begin
  17197.             select @cmd = N'
  17198.                 set identity_insert ' + @qualname + N' off '
  17199.             insert into #proctext(procedure_text) values( @cmd )
  17200.         end
  17201.     end
  17202.  
  17203.     --
  17204.     -- continue with scripting
  17205.     --
  17206.     select @cmd = N'
  17207.             end
  17208.  
  17209.             if (@cftcase = 11)
  17210.             begin
  17211.                 ' + N'--
  17212.                 ' + N'-- update using OLD_PK
  17213.                 ' + N'--'
  17214.     insert into #proctext(procedure_text) values( @cmd )
  17215.  
  17216.     --
  17217.     -- prepare the column list for update statement
  17218.     --
  17219.     select @num_col = 0
  17220.             ,@art_col = 0
  17221.     create table #worktab2 ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  17222.  
  17223.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  17224.     select colid from syscolumns where id = @objid order by colid asc
  17225.  
  17226.     OPEN hCColid
  17227.     FETCH hCColid INTO @this_col
  17228.     WHILE (@@fetch_status <> -1)
  17229.     begin
  17230.         -- Get the ordinal of the article partition or not.
  17231.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  17232.         if @isset = 0
  17233.         begin
  17234.             if ((@timestamp_subscribed = 1) and 
  17235.                     exists ( select * from dbo.syscolumns where id = @objid and colid = @this_col and xtype = 189))
  17236.                 select @art_col = @art_col + 1
  17237.         end
  17238.         else
  17239.             select @art_col = @art_col + 1
  17240.  
  17241.         exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 0, @colname output, @ccoltype output
  17242.         if @rc = 0 and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  17243.         begin
  17244.             if (rtrim(@ccoltype) != N'timestamp') and ColumnProperty(@objid, @colname, 'IsIdentity') != 1
  17245.             begin
  17246.                 select @num_col = @num_col + 1
  17247.                         ,@bytestr = cast((1 + (@art_col-1) / 8 ) as nvarchar)
  17248.                         ,@bitstr =  cast( power(2, (@art_col-1) % 8 ) as nvarchar)
  17249.  
  17250.                 select @column_string = quotename(@colname) + N' = case substring(@bitmap,' + 
  17251.                     @bytestr + N',1) & ' + @bitstr + N' when ' + @bitstr + 
  17252.                     N' then @c' + cast(@this_col as nvarchar(4)) + 
  17253.                     N' else @c' + cast(@this_col as nvarchar(4)) + N'_old  end '
  17254.  
  17255.                 if (@num_col = 1)
  17256.                 begin
  17257.                     select @column_string = N'
  17258.                     ' + @column_string
  17259.                 end
  17260.                 else
  17261.                 begin
  17262.                     select @column_string = N'
  17263.                     , ' + @column_string
  17264.                 end
  17265.  
  17266.                 insert into #worktab2(procedure_text) values( @column_string )
  17267.                 
  17268.             end
  17269.         end
  17270.         FETCH hCColid INTO @this_col
  17271.     end
  17272.     CLOSE hCColid
  17273.     DEALLOCATE hCColid
  17274.  
  17275.     --
  17276.     -- script the update with OLD_PK statement
  17277.     --
  17278.     select @cmd = N'
  17279.                 update ' + @qualname + N' set '
  17280.     insert into #proctext(procedure_text) values( @cmd )
  17281.     insert into #proctext(procedure_text) 
  17282.         select procedure_text from #worktab2 order by c1 asc
  17283.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  17284.     
  17285.     --
  17286.     -- continue with scripting
  17287.     --
  17288.     select @cmd = N'
  17289.             end
  17290.  
  17291.             if (@cftcase in (15, 16))
  17292.             begin
  17293.                 ' + N'--
  17294.                 ' + N'-- update using NEW_PK
  17295.                 ' + N'--'
  17296.     insert into #proctext(procedure_text) values( @cmd )
  17297.                 
  17298.     --
  17299.     -- script the update with NEW_PK statement
  17300.     --
  17301.     select @cmd = N'
  17302.                 update ' + @qualname + N' set '
  17303.     insert into #proctext(procedure_text) values( @cmd )
  17304.     insert into #proctext(procedure_text) 
  17305.         select procedure_text from #worktab2 order by c1 asc
  17306.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0
  17307.     
  17308.     --
  17309.     -- continue with scripting
  17310.     --
  17311.     select @cmd = N'
  17312.             end
  17313.  
  17314.             if (@cftcase in (14, 15))
  17315.             begin
  17316.                 ' + N'--
  17317.                 ' + N'-- Do not delete if subscriber has already
  17318.                 ' + N'-- updated this row as part of this transaction
  17319.                 ' + N'--'
  17320.     insert into #proctext(procedure_text) values( @cmd )
  17321.  
  17322.     --
  17323.     -- script the if exists code using OLD_PK and msprepl_tran_version
  17324.     --
  17325.     select @cmd = N'
  17326.                 if not exists (select * from ' + @qualname 
  17327.     insert into #proctext(procedure_text) values( @cmd )
  17328.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'subwins_check', 'msrepl_tran_version', 0
  17329.     insert into #proctext(procedure_text) values( N' )')
  17330.  
  17331.     select @cmd = N'
  17332.                 begin
  17333.                     ' + N'-- 
  17334.                     ' + N'-- delete row with OLD_PK
  17335.                     ' + N'--'
  17336.     insert into #proctext(procedure_text) values( @cmd )
  17337.  
  17338.     --
  17339.     -- script delete with OLD_PK
  17340.     --
  17341.     select @cmd = N'
  17342.                     delete ' + @qualname 
  17343.     insert into #proctext(procedure_text) values( @cmd )
  17344.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  17345.  
  17346.     --
  17347.     -- continue with rest of scripting
  17348.     --
  17349.     select @cmd = N'
  17350.                 end
  17351.             end
  17352.     
  17353.             if (@@error != 0)
  17354.                 return -1
  17355.  
  17356.             select @retcode = 0
  17357.         end
  17358.     end'
  17359.     insert into #proctext(procedure_text) values( @cmd )
  17360.  
  17361.     --
  17362.     -- all done
  17363.     --
  17364.     drop table #collisttab
  17365.     drop table #worktab
  17366.     drop table #worktab2
  17367.     return 0
  17368. END
  17369. go
  17370.  
  17371. EXEC dbo.sp_MS_marksystemobject sp_MSscript_update_subwins
  17372. GO
  17373.  
  17374. --
  17375. -- proc to generate publisher wins resolution code block
  17376. -- for update proc used for synctran/queued
  17377. --
  17378. raiserror('Creating procedure sp_MSscript_update_pubwins', 0,1)
  17379. go
  17380. create procedure sp_MSscript_update_pubwins (
  17381.     @publication sysname,
  17382.     @article     sysname, 
  17383.     @objid int,
  17384.     @columns binary(32) )
  17385. AS
  17386. BEGIN
  17387.     declare @cmd nvarchar(4000)
  17388.             ,@artid int
  17389.             ,@pubid int
  17390.             ,@dest_table sysname
  17391.             ,@dest_owner sysname
  17392.             ,@colname      sysname
  17393.             ,@ccoltype     sysname
  17394.             ,@this_col     int
  17395.             ,@rc           int
  17396.             ,@num_col      int
  17397.             ,@qualname nvarchar(512)
  17398.             ,@cast_str nvarchar(1000)
  17399.             ,@decl_str nvarchar(2000)
  17400.             ,@assign_str nvarchar(4000)
  17401.             ,@typestring nvarchar(100)
  17402.             ,@exec_str nvarchar(1000)
  17403.  
  17404.     --
  17405.     -- initialize the vars we will use
  17406.     --
  17407.     select @pubid = pubid from syspublications where name = @publication
  17408.     select @artid = artid, @dest_table = dest_table, @dest_owner = dest_owner
  17409.     from sysarticles where name = @article and pubid = @pubid
  17410.     select @dest_owner = case when (@dest_owner IS NULL) then N''
  17411.                 else quotename(@dest_owner) + N'.' end
  17412.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  17413.  
  17414.     --
  17415.     -- start scripting
  17416.     --
  17417.     select @cmd = N'
  17418.     else if (@error in (0, 547, 2627) and @execution_mode = @QPubWins)
  17419.     begin
  17420.         if (@rowcount = 1)
  17421.         begin
  17422.             ' + N'--
  17423.             ' + N'-- no conflict for this command
  17424.             ' + N'-- Check if PK update was being done
  17425.             ' + N'-- '
  17426.     insert into #proctext(procedure_text) values( @cmd )
  17427.  
  17428.     --
  17429.     -- script the PK update check
  17430.     --
  17431.     select @cmd = N'
  17432.             exec @retcode = dbo.sp_MSispkupdateinconflict ' + 
  17433.         cast(@pubid as nvarchar(10)) + N', ' + cast(@artid as nvarchar(10)) + N', @bitmap'
  17434.     insert into #proctext(procedure_text) values( @cmd )
  17435.  
  17436.     --
  17437.     -- continue scripting
  17438.     --
  17439.     select @cmd = N'
  17440.             if (@retcode = -1)
  17441.                 return -1
  17442.             if (@retcode = 0)
  17443.             begin
  17444.                 ' + N'--
  17445.                 ' + N'-- PK update is not being done
  17446.                 ' + N'-- generate delete + insert compensating action with OLD_PK
  17447.                 ' + N'-- 
  17448.                 select @cftcase = 0
  17449.             end'
  17450.     insert into #proctext(procedure_text) values( @cmd )
  17451.  
  17452.     --
  17453.     -- continue scripting
  17454.     --
  17455.     select @cmd = N'
  17456.             else
  17457.             begin
  17458.                 ' + N'--
  17459.                 ' + N'-- PK update is being done
  17460.                 ' + N'-- generate delete + insert compensating action with OLD_PK
  17461.                 ' + N'-- generate delete compensating action with NEW_PK
  17462.                 ' + N'-- 
  17463.                 select @cftcase = 1
  17464.             end
  17465.         end'
  17466.     insert into #proctext(procedure_text) values( @cmd )
  17467.  
  17468.     --
  17469.     -- continue scripting
  17470.     --
  17471.     select @cmd = N'
  17472.         else
  17473.         begin
  17474.             ' + N'--
  17475.             ' + N'-- Conflict for this command
  17476.             ' + N'-- Check if PK update was being done
  17477.             ' + N'--'
  17478.     insert into #proctext(procedure_text) values( @cmd )
  17479.  
  17480.     --
  17481.     -- script the PK update check
  17482.     --
  17483.     select @cmd = N'
  17484.             exec @retcode = dbo.sp_MSispkupdateinconflict ' + 
  17485.         cast(@pubid as nvarchar(10)) + N', ' + cast(@artid as nvarchar(10)) + N', @bitmap'
  17486.     insert into #proctext(procedure_text) values( @cmd )
  17487.  
  17488.     select @cmd = N'
  17489.             if (@retcode = -1)
  17490.                 return -1
  17491.             if (@retcode = 0)
  17492.             begin
  17493.                 ' + N'--
  17494.                 ' + N'-- PK update is not being done
  17495.                 ' + N'-- Now find the type of conflict
  17496.                 ' + N'-- '
  17497.     insert into #proctext(procedure_text) values( @cmd )
  17498.                 
  17499.     --
  17500.     -- script the if exists code using OLD_PK
  17501.     --
  17502.     select @cmd = N'
  17503.                 if exists (select * from ' + @qualname 
  17504.     insert into #proctext(procedure_text) values( @cmd )
  17505.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  17506.     insert into #proctext(procedure_text) values( N' )')
  17507.  
  17508.     --
  17509.     -- continue scripting
  17510.     --
  17511.     select @cmd = N'
  17512.                 begin
  17513.                     ' + N'--
  17514.                     ' + N'-- row exists
  17515.                     ' + N'-- generate delete + insert compensating action with OLD_PK
  17516.                     ' + N'--
  17517.                     select @cftcase = 11
  17518.                 end'
  17519.     insert into #proctext(procedure_text) values( @cmd )
  17520.     select @cmd = N'
  17521.                 else
  17522.                 begin
  17523.                     ' + N'--
  17524.                     ' + N'-- row does not exist
  17525.                     ' + N'-- generate delete compensating action with OLD_PK
  17526.                     ' + N'--
  17527.                     select @cftcase = 13
  17528.                 end
  17529.             end'
  17530.     insert into #proctext(procedure_text) values( @cmd )
  17531.             
  17532.     --
  17533.     -- continue scripting
  17534.     --
  17535.     select @cmd = N'
  17536.             else
  17537.             begin
  17538.                 ' + N'--
  17539.                 ' + N'-- PK update is being done
  17540.                 ' + N'-- Now find the type of conflict
  17541.                 ' + N'-- 
  17542.                 select @cftcase = 0'
  17543.     insert into #proctext(procedure_text) values( @cmd )
  17544.                 
  17545.     --
  17546.     -- script the if exists code using OLD_PK
  17547.     --
  17548.     select @cmd = N'
  17549.                 if exists (select * from ' + @qualname 
  17550.     insert into #proctext(procedure_text) values( @cmd )
  17551.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  17552.     insert into #proctext(procedure_text) values( N' )')
  17553.  
  17554.     --
  17555.     -- continue scripting
  17556.     --
  17557.     select @cmd = N'
  17558.                 begin
  17559.                     ' + N'--
  17560.                     ' + N'-- row with OLD_PK exists
  17561.                     ' + N'-- generate delete compensating action with OLD_PK +
  17562.                     ' + N'-- insert compensating action with OLD_PK 
  17563.                     ' + N'--
  17564.                     select @cftcase = 14
  17565.                 end'
  17566.     insert into #proctext(procedure_text) values( @cmd )
  17567.  
  17568.     --
  17569.     -- script the if exists code using NEW_PK
  17570.     --
  17571.     select @cmd = N'
  17572.                 if exists (select * from ' + @qualname 
  17573.     insert into #proctext(procedure_text) values( @cmd )
  17574.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0
  17575.     insert into #proctext(procedure_text) values( N' )')
  17576.  
  17577.     --
  17578.     -- continue scripting
  17579.     --
  17580.     select @cmd = N'
  17581.                 begin
  17582.                     ' + N'--
  17583.                     ' + N'-- row with NEW_PK exists
  17584.                     ' + N'-- case 15: rows with NEW_PK and OLD_PK exist
  17585.                     ' + N'-- generate delete compensating actions with OLD_PK, NEW_PK +
  17586.                     ' + N'-- insert compensating actions with OLD_PK, NEW_PK' 
  17587.     insert into #proctext(procedure_text) values( @cmd )
  17588.     select @cmd = N'
  17589.                     ' + N'-- case 16: row with NEW_PK exists and OLD_PK does not exist
  17590.                     ' + N'-- generate delete compensating action with OLD_PK, NEW_PK +
  17591.                     ' + N'-- insert compensating action with NEW_PK 
  17592.                     ' + N'--
  17593.                     select @cftcase = case when (@cftcase = 14) then 15 else 16 end
  17594.                 end'
  17595.     insert into #proctext(procedure_text) values( @cmd )
  17596.  
  17597.     --
  17598.     -- continue scripting
  17599.     --    
  17600.     select @cmd = N'
  17601.                 else
  17602.                 begin
  17603.                     ' + N'--
  17604.                     ' + N'-- row with NEW_PK does not exists
  17605.                     ' + N'-- case 12 : no existing rows with OLD_PK or NEW_PK
  17606.                     ' + N'-- generate delete compensating action with OLD_PK, NEW_PK '
  17607.     insert into #proctext(procedure_text) values( @cmd )
  17608.     select @cmd = N'
  17609.                     ' + N'-- case 17 : row with OLD_PK exist and NEW_PK does not exist 
  17610.                     ' + N'-- generate delete compensating action with OLD_PK, NEW_PK +
  17611.                     ' + N'-- insert compensating action with OLD_PK 
  17612.                     ' + N'-- 
  17613.                     select @cftcase = case when (@cftcase = 0) then 12 else 17 end 
  17614.                 end '
  17615.     insert into #proctext(procedure_text) values( @cmd )
  17616.     select @cmd = N'
  17617.             end
  17618.         end'         
  17619.     insert into #proctext(procedure_text) values( @cmd )
  17620.  
  17621.     --
  17622.     -- continue scripting
  17623.     --
  17624.     select @cmd = N'
  17625.         if (@cftcase in (0, 1, 11, 12, 13, 14, 15, 16, 17))
  17626.         begin
  17627.             ' + N'--
  17628.             ' + N'-- generation of delete compensating command with OLD_PK
  17629.             ' + N'--'
  17630.     insert into #proctext(procedure_text) values( @cmd )
  17631.  
  17632.     --
  17633.     -- generate delete compensating cmd with OLD_PK
  17634.     --
  17635.     select @cmd = N'
  17636.             select @cmd = ''DELETE ' + @dest_owner + quotename(@dest_table) + N' '' + '
  17637.     insert into #proctext(procedure_text) values( @cmd )
  17638.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'qcft_comp', NULL, 0, 'del'
  17639.     
  17640.     --
  17641.     -- script the sending command
  17642.     --
  17643.     exec sp_MSscript_compensating_send @pubid, @artid, 0, 1
  17644.     
  17645.     --
  17646.     -- continue scripting
  17647.     --
  17648.     select @cmd = N'
  17649.         end
  17650.         
  17651.         if (@cftcase in (1, 12, 15, 16, 17))
  17652.         begin
  17653.             ' + N'--
  17654.             ' + N'-- generation of delete compensating command with NEW_PK
  17655.             ' + N'--'
  17656.     insert into #proctext(procedure_text) values( @cmd )
  17657.  
  17658.     --
  17659.     -- generate delete compensating cmd with NEW_PK
  17660.     --
  17661.     select @cmd = N'
  17662.             select @cmd = ''DELETE ' + @dest_owner + quotename(@dest_table) + N' '' + '
  17663.     insert into #proctext(procedure_text) values( @cmd )
  17664.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'qcft_comp', NULL, 0, 'ins'
  17665.     
  17666.     --
  17667.     -- script the sending command
  17668.     --
  17669.     exec sp_MSscript_compensating_send @pubid, @artid, 0, 1
  17670.     
  17671.     --
  17672.     -- continue scripting
  17673.     --
  17674.     select @cmd = N'
  17675.         end
  17676.  
  17677.         if (@cftcase in (0, 1, 11, 14, 15, 17))
  17678.         begin
  17679.             ' + N'--
  17680.             ' + N'-- generate and send insert compensating command with OLD_PK
  17681.             ' + N'--'
  17682.     insert into #proctext(procedure_text) values( @cmd )
  17683.  
  17684.     --
  17685.     -- script compensating insert with OLD_PK
  17686.     --
  17687.     exec dbo.sp_MSscript_compensating_insert @publication, @article, @objid, @columns, 1
  17688.     
  17689.     --
  17690.     -- continue scripting
  17691.     --
  17692.     select @cmd = N'
  17693.         end
  17694.  
  17695.         if (@cftcase in (15, 16))
  17696.         begin
  17697.             ' + N'--
  17698.             ' + N'-- generate and send insert compensating command with NEW_PK
  17699.             ' + N'--'
  17700.     insert into #proctext(procedure_text) values( @cmd )
  17701.  
  17702.     --
  17703.     -- script compensating insert with NEW_PK
  17704.     --
  17705.     exec dbo.sp_MSscript_compensating_insert @publication, @article, @objid, @columns, 0
  17706.     
  17707.     --
  17708.     -- continue with scripting
  17709.     --
  17710.     select @cmd = N'
  17711.         end
  17712.         select @retcode = 0
  17713.     end'
  17714.     insert into #proctext(procedure_text) values( @cmd )
  17715.     
  17716.     --
  17717.     -- all done
  17718.     --
  17719.     return 0    
  17720. END
  17721. go
  17722.  
  17723. EXEC dbo.sp_MS_marksystemobject sp_MSscript_update_pubwins
  17724. GO
  17725.  
  17726. raiserror('Creating procedure sp_MSscript_delete_statement', 0,1)
  17727. go
  17728. create procedure sp_MSscript_delete_statement (
  17729.     @publication sysname,
  17730.     @article     sysname, 
  17731.     @objid int,
  17732.     @columns binary(32),
  17733.     @queued_pub bit = 0
  17734. )
  17735. as
  17736. BEGIN
  17737.     declare @cmd          nvarchar(4000)
  17738.     declare @qualname     nvarchar(512)
  17739.  
  17740.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  17741.  
  17742.     --
  17743.     -- start scripting
  17744.     --
  17745.     select @cmd = N'
  17746.     ' + N'--
  17747.     ' + N'-- detection/conflict resolution stage
  17748.     ' + N'--'
  17749.     
  17750.     if (@queued_pub = 1)
  17751.     begin
  17752.         select @cmd = @cmd + N'
  17753.     if (@execution_mode = @QPubWins)
  17754.         save tran cftpass
  17755.     '
  17756.     end
  17757.     insert into #proctext(procedure_text) values( @cmd )
  17758.  
  17759.     --
  17760.     -- delete statement
  17761.     --
  17762.     select @cmd = N'
  17763.     delete ' + @qualname 
  17764.     insert into #proctext(procedure_text) values( @cmd )
  17765.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', 'msrepl_tran_version', 4
  17766.  
  17767.     --
  17768.     -- continue with scripting
  17769.     --
  17770.     select @cmd = N'
  17771.     select @rowcount = @@ROWCOUNT, @error = @@ERROR
  17772.     '
  17773.  
  17774.     if (@queued_pub = 1)
  17775.     begin
  17776.         select @cmd = @cmd + N'
  17777.     if (@execution_mode = @QPubWins)
  17778.         rollback tran cftpass
  17779.     '
  17780.     end
  17781.     insert into #proctext(procedure_text) values( @cmd )
  17782.  
  17783.     --
  17784.     -- all done
  17785.     --
  17786.     return 0
  17787. END
  17788. go
  17789.  
  17790. EXEC dbo.sp_MS_marksystemobject sp_MSscript_delete_statement
  17791. GO
  17792.  
  17793. --
  17794. -- proc to generate subscriber wins resolution code block
  17795. -- for delete proc used for synctran/queued
  17796. --
  17797. raiserror('Creating procedure sp_MSscript_delete_subwins', 0,1)
  17798. go
  17799. create procedure sp_MSscript_delete_subwins (
  17800.     @publication sysname,
  17801.     @article     sysname, 
  17802.     @objid int,
  17803.     @columns binary(32) )
  17804. AS
  17805. BEGIN
  17806.     declare @cmd nvarchar(4000)
  17807.             ,@qualname nvarchar(512)
  17808.  
  17809.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  17810.  
  17811.     --
  17812.     -- start scripting
  17813.     --
  17814.     select @cmd = N'
  17815.     if (@error in (0, 547) and @execution_mode = @QSubWins)
  17816.     begin
  17817.         ' + N'--
  17818.         ' + N'-- Subscriber Wins resolution
  17819.         ' + N'--
  17820.         select @retcode = 0
  17821.         if (@rowcount = 0)
  17822.         begin
  17823.             --
  17824.             -- Conflict for this command
  17825.             -- Delete using PK only
  17826.             --'
  17827.     insert into #proctext(procedure_text) values( @cmd )
  17828.  
  17829.     --
  17830.     -- generate the delete statement
  17831.     --
  17832.     select @cmd = N'
  17833.             delete ' + @qualname 
  17834.     insert into #proctext(procedure_text) values( @cmd )
  17835.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  17836.  
  17837.     --
  17838.     -- continue with scripting
  17839.     --
  17840.     select @cmd = N'            
  17841.             if (@@error != 0 or @retcode != 0)
  17842.                 return -1
  17843.         end
  17844.     end'
  17845.     insert into #proctext(procedure_text) values( @cmd )
  17846.  
  17847.     --
  17848.     -- all done
  17849.     --
  17850.     return 0
  17851. END
  17852. go
  17853.  
  17854. EXEC dbo.sp_MS_marksystemobject sp_MSscript_delete_subwins
  17855. GO
  17856.  
  17857. --
  17858. -- proc that generates a compensating insert command string
  17859. -- specify the type of proc where this generation will be used
  17860. --
  17861. raiserror('Creating procedure sp_MSscript_compensating_insert', 0,1)
  17862. go
  17863. create procedure sp_MSscript_compensating_insert (
  17864.     @publication sysname,
  17865.     @article     sysname, 
  17866.     @objid int,
  17867.     @columns binary(32),
  17868.     @proctype    int = 1)        -- 0 = use new_pk, 1 = use old_pk
  17869. AS
  17870. BEGIN
  17871.     declare @cmd nvarchar(4000)
  17872.             ,@artid int
  17873.             ,@pubid int
  17874.             ,@dest_table sysname
  17875.             ,@dest_owner sysname
  17876.             ,@colname      sysname
  17877.             ,@ccoltype     sysname
  17878.             ,@this_col     int
  17879.             ,@rc           int
  17880.             ,@num_col      int
  17881.             ,@qualname nvarchar(512)
  17882.             ,@cast_str nvarchar(4000)
  17883.             ,@column_string nvarchar(4000)
  17884.             ,@ins_cmd nvarchar(255)
  17885.             ,@startoffset int
  17886.             ,@setprefix bit
  17887.             ,@commandlen int
  17888.             ,@fragmentlen int
  17889.             ,@collen int
  17890.             ,@first_time bit
  17891.             ,@fullcastlen int
  17892.             ,@splitlen int
  17893.  
  17894.     --
  17895.     -- initialize the vars we will use
  17896.     --
  17897.     select @pubid = pubid from syspublications where name = @publication
  17898.     select @artid = artid, @dest_table = dest_table, 
  17899.         @dest_owner = dest_owner, @ins_cmd = ins_cmd from sysarticles 
  17900.     where name = @article and pubid = @pubid
  17901.     select @dest_owner = case when (@dest_owner IS NULL) then N''
  17902.                 else quotename(@dest_owner) + N'.' end
  17903.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  17904.  
  17905.     --
  17906.     -- The compensating command will be split into one or more
  17907.     -- fragment commands if the length exceeds 3450 characters in length 
  17908.     -- (to accomodate compensating server/db names)
  17909.     -- For correctly estimating the length of the compensating command
  17910.     -- we have to take the max column length of the data into consideration along
  17911.     -- with the scripting command length
  17912.     --
  17913.  
  17914.     --
  17915.     -- use the insert command if available
  17916.     --
  17917.     select @commandlen = 0
  17918.             ,@setprefix = 1
  17919.  
  17920.     if (@ins_cmd = N'SQL')
  17921.     begin
  17922.         select @cmd = N'
  17923.             select @cmd = ''INSERT INTO ' + @dest_owner + quotename(@dest_table) + N''' + 
  17924.                          '' SELECT '' + '
  17925.     end
  17926.     else
  17927.     begin
  17928.         select @cmd = N'
  17929.             select @cmd = ''EXEC ' + substring(@ins_cmd, 5, len(@ins_cmd) - 4) + N' '' + '
  17930.     end
  17931.     insert into #proctext(procedure_text) values( @cmd )
  17932.      select @commandlen = @commandlen + len(@cmd)
  17933.     
  17934.     select @num_col = 0
  17935.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  17936.     select colid, length from syscolumns where id = @objid order by colid asc
  17937.  
  17938.     OPEN hCColid
  17939.     FETCH hCColid INTO @this_col, @collen
  17940.     WHILE (@@fetch_status != -1)
  17941.     begin
  17942.         exec @rc = dbo.sp_MSget_colinfo @objid, @this_col, @columns, 1, @colname output, @ccoltype output
  17943.         if @rc = 0  and EXISTS (select name from syscolumns where id=@objid and colid=@this_col and iscomputed<>1)
  17944.         begin
  17945.             if rtrim(@ccoltype) not like N'timestamp' 
  17946.             begin
  17947.                 select @num_col = @num_col + 1
  17948.  
  17949.                 --
  17950.                 -- Compute the command fragment length needed for this column
  17951.                 -- based on the coltype
  17952.                 --                
  17953.                 if (lower(@ccoltype) in ('ntext','text','image'))
  17954.                 begin
  17955.                     --
  17956.                     -- For compensating commands we have to include the text and image data
  17957.                     -- as the custom procs used by Distribution process expects them - as it
  17958.                     -- done for regular transactional replication - but we will only send NULLs
  17959.                     -- as it is not possible to ascertain the size of the data during the generation
  17960.                     --        
  17961.                     select @cast_str = N' ''null'' '
  17962.                     select @fullcastlen = len(@cast_str)
  17963.                     select @fragmentlen = @fullcastlen + 4 + @collen
  17964.                 end
  17965.                 else if (lower(@ccoltype) in ('varchar','nvarchar','char','nchar'))
  17966.                 begin
  17967.                     if (lower(@ccoltype) in ('nvarchar', 'nchar'))
  17968.                         select @collen = (@collen / 2)
  17969.     
  17970.                     select @cast_str = case 
  17971.                             when (lower(@ccoltype) in ('nvarchar', 'nchar'))
  17972.                                 then N' ISNULL(''N'''''' + master.dbo.fn_MSgensqescstr(' + quotename(@colname) + N') collate database_default + '''''''', ''null'') '
  17973.                                 else N' ISNULL('''''''' + master.dbo.fn_MSgensqescstr(' + quotename(@colname) + N') collate database_default + '''''''', ''null'') '
  17974.                             end
  17975.        
  17976.                     select @fullcastlen = len(@cast_str)
  17977.                     select @fragmentlen = @fullcastlen + 4 + @collen
  17978.                 end
  17979.                 else if (lower(@ccoltype) in ('binary','varbinary'))
  17980.                 begin
  17981.                     --
  17982.                     -- each byte has 2 nibbles - we need a char to represent each nibble
  17983.                     --
  17984.                     select @collen = @collen * 2
  17985.                     select @cast_str = N' ISNULL(master.dbo.fn_varbintohexsubstring(1,' + quotename(@colname) + N',1,0) collate database_default, ''null'') '
  17986.                     select @fullcastlen = len(@cast_str)
  17987.                     select @fragmentlen = @fullcastlen + 4 + @collen + 2
  17988.                 end
  17989.                 else if (lower(@ccoltype) in ('bit','bigint','int','smallint','tinyint','float','real','decimal','numeric'))
  17990.                 begin
  17991.                     select @collen = 40
  17992.                     select @cast_str = N' ISNULL(CAST(' + quotename(@colname) + N' as nvarchar), ''null'') '
  17993.                     select @fragmentlen = len(@cast_str) + @collen
  17994.                 end
  17995.                 else if (lower(@ccoltype) in ('money','smallmoney'))
  17996.                 begin
  17997.                     select @collen = 40
  17998.                     select @cast_str = N' ISNULL(CONVERT(nvarchar(40),' + quotename(@colname) + N',2), ''null'') '
  17999.                     select @fragmentlen = len(@cast_str) + @collen
  18000.                 end
  18001.                 else if (lower(@ccoltype) = 'uniqueidentifier')
  18002.                 begin
  18003.                     select @collen = 40
  18004.                     select @cast_str = N' ISNULL('''''''' + CAST(' + quotename(@colname) + N' as nvarchar(40)) + '''''''', ''null'') '
  18005.                     select @fragmentlen = len(@cast_str) + @collen
  18006.                 end
  18007.                 else if (lower(@ccoltype) in ('datetime','smalldatetime'))
  18008.                 begin
  18009.                     select @collen = 40
  18010.                     select @cast_str = N' ISNULL('''''''' + CONVERT(nvarchar(40), ' + quotename(@colname) + N', 121) + '''''''', ''null'') '
  18011.                     select @fragmentlen = len(@cast_str) + @collen
  18012.                 end
  18013.                 else if (lower(@ccoltype) = 'sql_variant')
  18014.                 begin
  18015.                     --
  18016.                     -- need to revisit this later
  18017.                     --
  18018.                     select @cast_str = N' ISNULL(master.dbo.fn_sqlvarbasetostr(' + quotename(@colname) + N' ) collate database_default, ''null'') '
  18019.                     select @fragmentlen = len(@cast_str) + @collen
  18020.                 end                    
  18021.                 else
  18022.                 begin
  18023.                     select @collen = 40
  18024.                     select @cast_str = N' ISNULL(CAST(' + quotename(@colname) + N' as nvarchar), ''null'') '
  18025.                     select @fragmentlen = len(@cast_str) + @collen
  18026.                 end
  18027.             
  18028.                 --
  18029.                 -- for fixed datatypes - we will not split the data at all we will
  18030.                 -- flush the command script and continue
  18031.                 -- for varying/large datatypes, we will have to split data if necessary
  18032.                 --
  18033.                 if ((lower(@ccoltype) in ('varchar','nvarchar','char','nchar','binary','varbinary')) 
  18034.                         and (@fragmentlen + @commandlen > 3450))
  18035.                 begin
  18036.                      --
  18037.                      -- the column length is too big, we have to break the data string
  18038.                      -- initialize
  18039.                      --
  18040.                     if (@num_col = 1)
  18041.                     begin
  18042.                         select @column_string = N'
  18043.                 ' 
  18044.                     end
  18045.                     else
  18046.                     begin
  18047.                         select @column_string = N'
  18048.                 + '','' + ' 
  18049.                     end
  18050.  
  18051.                     --
  18052.                     -- use substring to break the string value in the
  18053.                     -- compensating command
  18054.                     --
  18055.                     select @first_time = 1
  18056.                             ,@startoffset = 1
  18057.                     while (@collen > 0)
  18058.                     begin
  18059.                          select @splitlen = case when ((@first_time = 1) or (@collen > 3450))
  18060.                                                  then (3450 - @commandlen - 30 - @fullcastlen)
  18061.                                                  else @collen end
  18062.  
  18063.                         --
  18064.                         -- Do we need to put quotes (many datatypes need it)
  18065.                         --
  18066.                          if (@first_time = 1)
  18067.                          begin
  18068.                             if (lower(@ccoltype) in ('varchar','nvarchar','char','nchar'))
  18069.                                 select @column_string = case 
  18070.                                     when (lower(@ccoltype) in ('nvarchar', 'nchar'))
  18071.                                         then @column_string + N' ISNULL(''N'''''' + master.dbo.fn_MSgensqescstr( '
  18072.                                         else @column_string + N' ISNULL('''''''' + master.dbo.fn_MSgensqescstr( '
  18073.                                     end
  18074.                             else if (lower(@ccoltype) in ('binary','varbinary'))
  18075.                                 select @column_string = @column_string + N' ISNULL(master.dbo.fn_varbintohexsubstring(1,' 
  18076.                         end
  18077.                          else
  18078.                          begin
  18079.                             if (lower(@ccoltype) in ('varchar','nvarchar','char','nchar'))
  18080.                                  select @column_string = N' + ISNULL(master.dbo.fn_MSgensqescstr( '
  18081.                             else if (lower(@ccoltype) in ('binary','varbinary'))
  18082.                                 select @column_string = @column_string + N' + ISNULL(master.dbo.fn_varbintohexsubstring(0,' 
  18083.                          end
  18084.  
  18085.                         --
  18086.                         -- prepare the substring script
  18087.                         --
  18088.                         if (lower(@ccoltype) in ('varchar','nvarchar','char','nchar'))
  18089.                             select @cast_str = N'SUBSTRING(' + quotename(@colname) + N', ' + cast(@startoffset as nvarchar) + N', ' +  cast(@splitlen as nvarchar) + N')'
  18090.                         else if (lower(@ccoltype) in ('binary','varbinary'))
  18091.                             select @cast_str = quotename(@colname) + N', ' + cast(@startoffset as nvarchar) + N', ' +  cast((@splitlen/2) as nvarchar)
  18092.  
  18093.                         if (@first_time = 1)
  18094.                          begin
  18095.                             select @cast_str = @cast_str + N') collate database_default, ''null'') '
  18096.                                     ,@first_time = 0
  18097.                          end
  18098.                          else
  18099.                          begin
  18100.                             select @cast_str = @cast_str + N') collate database_default, '''') '
  18101.  
  18102.                             if (@collen - @splitlen < 1)
  18103.                             begin
  18104.                                 if (lower(@ccoltype) in ('varchar','nvarchar','char','nchar'))
  18105.                                     select @cast_str = @cast_str + N' + '''''''' '
  18106.                             end
  18107.                         end
  18108.                                  
  18109.                         select @column_string = @column_string + @cast_str
  18110.                         insert into #proctext(procedure_text) values( @column_string )
  18111.  
  18112.                         if (@fragmentlen + @commandlen > 3450)
  18113.                         begin
  18114.                             select @cmd = N'
  18115.             from ' + @qualname 
  18116.                             insert into #proctext(procedure_text) values( @cmd )
  18117.                             if (@proctype = 1)
  18118.                                 exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0, 'del'
  18119.                             else
  18120.                                 exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0, 'ins'
  18121.                             exec sp_MSscript_compensating_send @pubid, @artid, 1, @setprefix
  18122.                             if (@setprefix = 1)
  18123.                                 select @setprefix = 0
  18124.  
  18125.                             select @cmd = N'
  18126.             select @cmd = N''''' 
  18127.                             insert into #proctext(procedure_text) values( @cmd )
  18128.                             select @commandlen = 0
  18129.                         end
  18130.                         else
  18131.                             select @commandlen = @commandlen + len(@column_string)
  18132.  
  18133.                         --
  18134.                         -- update vars for next round
  18135.                         --
  18136.                         select @collen = @collen - @splitlen
  18137.                                 ,@column_string = N''
  18138.                                 ,@startoffset = case 
  18139.                                     when (lower(@ccoltype) in ('binary','varbinary')) 
  18140.                                         then (@splitlen/2) + @startoffset 
  18141.                                         else @splitlen + @startoffset 
  18142.                                     end
  18143.                         select @fragmentlen = @fullcastlen + 4 + @collen
  18144.                     end                            
  18145.  
  18146.                     --
  18147.                     -- we done with this column now
  18148.                     -- skip processing further and continue
  18149.                     --                        
  18150.                     select @commandlen = @commandlen + len(@column_string)
  18151.                  end
  18152.                  else
  18153.                  begin
  18154.                     --
  18155.                     -- Handling general fixed type column cases
  18156.                     --
  18157.                     if (@num_col = 1)
  18158.                     begin
  18159.                         select @column_string = N'
  18160.                 ' + @cast_str
  18161.                     end
  18162.                     else
  18163.                     begin
  18164.                         select @column_string = N'
  18165.                 + '','' + ' + @cast_str
  18166.                     end
  18167.  
  18168.                     --
  18169.                     -- check if we need to flush the command first
  18170.                     --
  18171.                     if (@fragmentlen + len(@column_string) + @commandlen > 3450)
  18172.                     begin
  18173.                         --
  18174.                         -- send this compensating command first
  18175.                         --
  18176.                         select @cmd = N'
  18177.             from ' + @qualname 
  18178.                         insert into #proctext(procedure_text) values( @cmd )
  18179.  
  18180.                         if (@proctype = 1)
  18181.                             exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0, 'del'
  18182.                         else
  18183.                             exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0, 'ins'
  18184.         
  18185.                         exec sp_MSscript_compensating_send @pubid, @artid, 1, @setprefix
  18186.                         if (@setprefix = 1)
  18187.                             select @setprefix = 0
  18188.  
  18189.                         select @cmd = N'
  18190.             select @cmd = N'' ''' 
  18191.                         insert into #proctext(procedure_text) values( @cmd )
  18192.                         select @commandlen = 0                    
  18193.                     end
  18194.  
  18195.                     --
  18196.                     -- script out the column string
  18197.                     --
  18198.                     insert into #proctext(procedure_text) values( @column_string )
  18199.  
  18200.                     --
  18201.                     -- if we are processing sql_variants, flush the command again
  18202.                     --
  18203.                     if (lower(@ccoltype) = 'sql_variant')
  18204.                     begin
  18205.                         --
  18206.                         -- send this compensating command first
  18207.                         --
  18208.                         select @cmd = N'
  18209.             from ' + @qualname 
  18210.                         insert into #proctext(procedure_text) values( @cmd )
  18211.  
  18212.                         if (@proctype = 1)
  18213.                             exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0, 'del'
  18214.                         else
  18215.                             exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0, 'ins'
  18216.         
  18217.                         exec sp_MSscript_compensating_send @pubid, @artid, 1, @setprefix
  18218.                         if (@setprefix = 1)
  18219.                             select @setprefix = 0
  18220.  
  18221.                         select @cmd = N'
  18222.             select @cmd = N'' ''' 
  18223.                         insert into #proctext(procedure_text) values( @cmd )
  18224.                         select @commandlen = 0                    
  18225.                     end
  18226.                     else
  18227.                         select @commandlen = @commandlen + @fragmentlen + len(@column_string)
  18228.                 end
  18229.             end
  18230.         end
  18231.  
  18232.         --
  18233.         -- process the next column
  18234.         --
  18235.         FETCH hCColid INTO @this_col, @collen
  18236.     end
  18237.     CLOSE hCColid
  18238.     DEALLOCATE hCColid
  18239.  
  18240.     --
  18241.     -- Check if we need to flush the command one more time (final)
  18242.     --
  18243.     if (@commandlen > 0)
  18244.     begin
  18245.         --
  18246.         -- send the last fragment of the command
  18247.         --
  18248.         select @cmd = N'
  18249.             from ' + @qualname 
  18250.         insert into #proctext(procedure_text) values( @cmd )
  18251.  
  18252.         if (@proctype = 1)
  18253.             exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0, 'del'
  18254.         else
  18255.             exec dbo.sp_MSscript_where_clause @objid, @columns, 'new_pk_q', NULL, 0, 'ins'
  18256.         exec sp_MSscript_compensating_send @pubid, @artid, 0, @setprefix
  18257.     end
  18258.  
  18259.     --
  18260.     -- all done
  18261.     --
  18262.     return 0
  18263. END
  18264. go
  18265.  
  18266. EXEC dbo.sp_MS_marksystemobject sp_MSscript_compensating_insert
  18267. GO
  18268.  
  18269. --
  18270. -- proc to generate publisher wins resolution code block
  18271. -- for delete proc used for synctran/queued
  18272. --
  18273. raiserror('Creating procedure sp_MSscript_delete_pubwins', 0,1)
  18274. go
  18275. create procedure sp_MSscript_delete_pubwins (
  18276.     @publication sysname,
  18277.     @article     sysname, 
  18278.     @objid int,
  18279.     @columns binary(32) )
  18280. AS
  18281. BEGIN
  18282.     declare @cmd nvarchar(4000)
  18283.             ,@artid int
  18284.             ,@pubid int
  18285.             ,@dest_table sysname
  18286.             ,@qualname nvarchar(512)
  18287.  
  18288.     --
  18289.     -- initialize the vars we will use
  18290.     --
  18291.     select @pubid = pubid from syspublications where name = @publication
  18292.     select @artid = artid, @dest_table = dest_table from sysarticles 
  18293.         where name = @article and pubid = @pubid
  18294.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  18295.  
  18296.     --
  18297.     -- start scripting
  18298.     --
  18299.     select @cmd = N'
  18300.     else if (@error in (0, 547) and @execution_mode = @QPubWins)
  18301.     begin
  18302.         ' + N'--
  18303.         ' + N'-- Publisher Wins resolution
  18304.         ' + N'-- Find where we have to generate compensating action
  18305.         ' + N'--
  18306.         if (@rowcount = 1)
  18307.         begin
  18308.             ' + N'--
  18309.             ' + N'-- no conflict for this command
  18310.             ' + N'-- generate insert compensating action
  18311.             ' + N'--            
  18312.             select @cftcase = 0
  18313.         end
  18314.         else
  18315.         begin
  18316.             ' + N'--
  18317.             ' + N'-- conflict for this command
  18318.             ' + N'--'
  18319.     insert into #proctext(procedure_text) values( @cmd )
  18320.             
  18321.     --
  18322.     -- script the if exists code
  18323.     --
  18324.     select @cmd = N'
  18325.             if exists (select * from ' + @qualname 
  18326.     insert into #proctext(procedure_text) values( @cmd )
  18327.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'upd version', NULL, 0
  18328.     insert into #proctext(procedure_text) values( N'            )')
  18329.  
  18330.     --
  18331.     -- continue with scripting
  18332.     --
  18333.     select @cmd = N'
  18334.             begin
  18335.                 ' + N'--
  18336.                 ' + N'-- row exists
  18337.                 ' + N'-- generate insert compensating action
  18338.                 ' + N'--
  18339.                 select @cftcase = 31
  18340.             end
  18341.             else
  18342.             begin
  18343.                 ' + N'--
  18344.                 ' + N'-- row does not exist
  18345.                 ' + N'-- do nothing
  18346.                 ' + N'--
  18347.                 select @cftcase = 33
  18348.             end
  18349.         end'
  18350.     insert into #proctext(procedure_text) values( @cmd )
  18351.         
  18352.     select @cmd = N'
  18353.         if (@cftcase in (0, 31))
  18354.         begin
  18355.             ' + N'--
  18356.             ' + N'-- generation and sending of compensating command
  18357.             ' + N'--'
  18358.     insert into #proctext(procedure_text) values( @cmd )
  18359.  
  18360.     --
  18361.     -- generate the compensating update command
  18362.     --
  18363.     exec dbo.sp_MSscript_compensating_insert @publication, @article, @objid, @columns, 1
  18364.  
  18365.     --
  18366.     -- continue with scripting
  18367.     --
  18368.     select @cmd = N'
  18369.         end
  18370.         select @retcode = 0
  18371.     end'
  18372.     insert into #proctext(procedure_text) values( @cmd )
  18373.  
  18374.     --
  18375.     -- all done
  18376.     --
  18377.     return 0    
  18378. END
  18379. go
  18380.  
  18381. EXEC dbo.sp_MS_marksystemobject sp_MSscript_delete_pubwins
  18382. GO
  18383.  
  18384. raiserror('Creating procedure sp_MSscript_beginproc', 0,1)
  18385. go
  18386. create procedure sp_MSscript_beginproc (
  18387.     @publication  sysname, 
  18388.     @article      sysname, 
  18389.     @procname     sysname,
  18390.     @source_objid int        output,
  18391.     @columns      binary(32) output)
  18392. as
  18393. BEGIN
  18394.     declare @cmd nvarchar(4000)
  18395.     declare @source_table sysname
  18396.     declare @owner sysname
  18397.  
  18398.     -- Retrieve underlying table name and replicated columns
  18399.     select @source_table = object_name(objid), @source_objid = objid, @columns = columns from sysarticles a, syspublications p
  18400.         where a.name = @article and
  18401.               p.name = @publication and
  18402.               a.pubid = p.pubid
  18403.  
  18404.     -- Get the object owner name
  18405.     select @owner = u.name from sysusers u, sysobjects o where 
  18406.         o.id = @source_objid and
  18407.         o.uid = u.uid
  18408.             
  18409.     if @source_table IS NULL
  18410.     begin
  18411.         raiserror (20506, 16, 1,  @source_table, 'sp_MSscript_beginproc')
  18412.         return 0
  18413.     end
  18414.  
  18415.     -- Construct proc name
  18416.     -- Create proc under the table owner account to preserve the ownership chain
  18417.     select @cmd = N'create procedure '+QUOTENAME(@owner)+ N'.'+ QUOTENAME(@procname) + N' (
  18418.     @orig_server sysname, @orig_db sysname,'
  18419.     exec dbo.sp_MSflush_command @cmd output, 1
  18420.  
  18421.     return 1
  18422. END
  18423. go
  18424.  
  18425. EXEC dbo.sp_MS_marksystemobject sp_MSscript_beginproc
  18426. GO
  18427.  
  18428. raiserror('Creating procedure sp_MSscript_security', 0,1)
  18429. go
  18430. create procedure sp_MSscript_security (
  18431.     @publication sysname)
  18432. as
  18433. BEGIN
  18434.     declare @cmd nvarchar(4000)
  18435.     
  18436.     select @cmd = N'
  18437.     ' + N'--
  18438.     ' + N'-- Check for security
  18439.     ' + N'--
  18440.     exec @retcode = dbo.sp_MSreplcheck_pull @publication = '+ quotename(@publication) + N'
  18441.     if (@retcode != 0 or @@error != 0)
  18442.         return -1
  18443.     '
  18444.     insert into #proctext(procedure_text) values(@cmd)
  18445. END                    
  18446. go
  18447.  
  18448. EXEC dbo.sp_MS_marksystemobject sp_MSscript_security
  18449. GO
  18450.  
  18451. raiserror('Creating procedure sp_MSscript_endproc', 0,1)
  18452. go
  18453. create procedure sp_MSscript_endproc (
  18454.     @objid int, 
  18455.     @op_type varchar(3) = 'ins', -- 'ins', 'upd', 'del'
  18456.     @columns binary(32),
  18457.     @outvars nvarchar(4000),
  18458.     @queued_pub bit = 0
  18459. )
  18460. as
  18461. BEGIN
  18462.     declare @cmd nvarchar(4000)
  18463.     declare @qualname nvarchar(512)
  18464.  
  18465.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  18466.  
  18467.     --
  18468.     -- start scripting
  18469.     --
  18470.     select @cmd = N'
  18471.     ' + N'--
  18472.     ' + N'-- decide the return code
  18473.     ' + N'--
  18474.     if (@execution_mode = @immediate)
  18475.     begin
  18476.         if @error != 0
  18477.               return -1
  18478.         -- Return special code to indicate the subscriber row needs to be
  18479.         -- refreshed.
  18480.         if @rowcount = 0
  18481.               return 5
  18482.     end'
  18483.     insert into #proctext(procedure_text) values(@cmd)
  18484.  
  18485.     --
  18486.     -- operation specific stuff
  18487.     --
  18488.     if (@queued_pub = 1)
  18489.     begin
  18490.         if (@op_type = 'ins')
  18491.         begin
  18492.             select @cmd = N'
  18493.     if (@execution_mode = @QFirstPass)
  18494.     begin
  18495.         if (@rowcount = 0)
  18496.         begin
  18497.             if (@error in (547, 2627))
  18498.                 return 2 -- insert conflict
  18499.             else
  18500.                 return -1 -- error
  18501.         end
  18502.     end'
  18503.         end
  18504.         else if (@op_type = 'upd')
  18505.         begin
  18506.             select @cmd = N'
  18507.     if (@execution_mode = @QFirstPass)
  18508.     begin
  18509.         if (@rowcount = 0)
  18510.         begin
  18511.             if (@error in (0, 547, 2627))
  18512.                 return 1 -- update conflict
  18513.             else
  18514.                 return -1 -- error
  18515.         end
  18516.     end'
  18517.         end
  18518.         else if (@op_type = 'del')
  18519.         begin
  18520.             select @cmd = N'
  18521.     if (@execution_mode = @QFirstPass)
  18522.     begin
  18523.         if (@rowcount = 0)
  18524.         begin
  18525.             if (@error in (0, 547))
  18526.                 return 3 -- delete conflict
  18527.             else
  18528.                 return -1 -- error
  18529.         end
  18530.     end'
  18531.         end
  18532.         insert into #proctext(procedure_text) values(@cmd)
  18533.         
  18534.         --
  18535.         -- continue with scripting
  18536.         --
  18537.         select @cmd = N'
  18538.     
  18539.     if (@execution_mode in (@QPubWins, @QSubWins))
  18540.     begin        
  18541.         if (@@error != 0 or @retcode != 0)
  18542.             return -1 -- error
  18543.     end
  18544.     '
  18545.         insert into #proctext(procedure_text) values(@cmd)
  18546.     end
  18547.  
  18548.     --
  18549.     -- if we have output vars to assign do it now
  18550.     --
  18551.     if (@outvars is not null)
  18552.     begin   
  18553.         if @op_type = 'upd'
  18554.         begin
  18555.             --
  18556.             -- Script out pk var assigment that used in sp_MSscript_where_clause
  18557.             --
  18558.             exec dbo.sp_MSscript_pkvar_assignment @objid, @columns, 1
  18559.             insert into #proctext(procedure_text) values(N'
  18560.     ')
  18561.         end
  18562.  
  18563.         select @cmd = N'
  18564.     select ' + @outvars + N'
  18565.     from ' + @qualname 
  18566.         insert into #proctext(procedure_text) values( @cmd)
  18567.         insert into #proctext(procedure_text) values( N'
  18568.     ')
  18569.     
  18570.         if (@op_type = 'ins')
  18571.             exec dbo.sp_MSscript_where_clause @objid, @columns, 'new pk', null, 4
  18572.         else if (@op_type = 'upd')
  18573.             exec dbo.sp_MSscript_where_clause @objid, @columns, 'old pk', null, 4
  18574.     end
  18575.  
  18576.     --
  18577.     -- Final part of the proc
  18578.     --
  18579.     select @cmd = N'
  18580.     
  18581.     ' + N'--
  18582.     ' + N'-- past all checks
  18583.     ' + N'--
  18584.     return 0
  18585. END
  18586. '
  18587.     insert into #proctext(procedure_text) values(@cmd)
  18588.     
  18589.     --
  18590.     -- all done
  18591.     --
  18592.     return 0
  18593. END
  18594. go
  18595.  
  18596. EXEC dbo.sp_MS_marksystemobject sp_MSscript_endproc
  18597. GO
  18598.  
  18599.  
  18600. raiserror('Creating procedure sp_MStable_not_modifiable', 0,1)
  18601. go
  18602. create proc sp_MStable_not_modifiable
  18603.     @objid   int,
  18604.     @columns binary(32)
  18605. as
  18606.     declare @colname      sysname
  18607.     declare @typestring   nvarchar(4000)
  18608.     declare @this_col     int
  18609.     declare @art_col      int
  18610.     declare @isset        int
  18611.     declare @found int, @repl_columns int
  18612.  
  18613.     select @art_col = 1
  18614.     select @found = 0, @repl_columns = 0
  18615.  
  18616.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  18617.     select colid from syscolumns where id = @objid order by colid asc
  18618.  
  18619.     OPEN hCColid
  18620.  
  18621.     FETCH hCColid INTO @this_col
  18622.  
  18623.     WHILE (@@fetch_status <> -1)
  18624.     begin
  18625.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  18626.  
  18627.         if @isset != 0 and EXISTS (select name from syscolumns where id=@objid and @this_col=colid and iscomputed<>1)
  18628.         begin
  18629.             select @repl_columns = @repl_columns + 1
  18630.             exec dbo.sp_MSget_type @objid, @this_col, @colname output, @typestring OUTPUT
  18631.  
  18632.             if @typestring = N'timestamp' or ColumnProperty(@objid, @colname, 'IsIdentity') = 1
  18633.                 select @found = 1
  18634.  
  18635.         end
  18636.         FETCH hCColid INTO @this_col
  18637.     end
  18638.     CLOSE hCColid
  18639.     DEALLOCATE hCColid
  18640.  
  18641.     if @found = 1 and @repl_columns = 1
  18642.         return 1
  18643.     else
  18644.         return 0
  18645. go
  18646.  
  18647.  
  18648. EXEC dbo.sp_MS_marksystemobject sp_MStable_not_modifiable
  18649. GO
  18650.  
  18651. --
  18652. -- proc to script the various checks done for queued and
  18653. -- synctran execution prior to actual detection/resolution
  18654. -- For queued execution, we also check for Reinitialization
  18655. -- phase
  18656. --
  18657. raiserror('Creating procedure sp_MSscript_ExecutionMode_stmt', 0,1)
  18658. go
  18659. create procedure sp_MSscript_ExecutionMode_stmt (
  18660.     @publication sysname, 
  18661.     @article     sysname,
  18662.     @proctype    int = 0)        -- 0 insert, 1 delete, 2 update
  18663. as
  18664. begin
  18665.     declare @cmd        nvarchar(4000)
  18666.             ,@artid        int
  18667.             ,@pubid        int
  18668.             ,@queued_pub bit
  18669.  
  18670.     select @pubid = pubid, @queued_pub = allow_queued_tran 
  18671.         from syspublications where name = @publication
  18672.     select @artid = artid from sysarticles where name = @article and pubid = @pubid
  18673.  
  18674.     --
  18675.     -- For queued execution check if we are in the phase of reinitialization
  18676.     --
  18677.     select @cmd = N'
  18678.     ' + N'--
  18679.     ' + N'-- Check if we are in the process of Reinitialization
  18680.     ' + N'-- if yes then return
  18681.     ' + N'--' 
  18682.     insert into #proctext(procedure_text) values( @cmd )
  18683.  
  18684.     select @cmd = N'
  18685.     exec @retcode = dbo.sp_MSgetarticlereinitvalue @orig_server, @orig_db, ' + 
  18686.     cast(@artid as nvarchar(5)) + N', @reinit output
  18687.     if (@retcode != 0 or @@error != 0)
  18688.         return -1 '
  18689.     insert into #proctext(procedure_text) values( @cmd )
  18690.  
  18691.     select @cmd = N'
  18692.     if (@reinit = 1) -- Resync state
  18693.     begin
  18694.         if (@execution_mode = @immediate)
  18695.             return -2'
  18696.     if (@queued_pub = 1)
  18697.     begin
  18698.         select @cmd = @cmd + N'
  18699.         else
  18700.             return 4 -- Queued Resync state'
  18701.     end
  18702.     select @cmd = @cmd + N'
  18703.     end
  18704.     '
  18705.     insert into #proctext(procedure_text) values( @cmd )
  18706.     
  18707.     --
  18708.     -- set loopback detection for immediate
  18709.     --
  18710.     select @cmd = N'
  18711.     if (@execution_mode = @immediate)
  18712.     begin
  18713.         ' + N'--
  18714.         ' + N'-- For immediate
  18715.         ' + N'-- enable loopback detection
  18716.         ' + N'--
  18717.         exec @retcode = dbo.sp_replsetoriginator @orig_server, @orig_db
  18718.         if (@retcode != 0 or @@error != 0) 
  18719.             return -1
  18720.     end'
  18721.     insert into #proctext(procedure_text) values( @cmd )
  18722.  
  18723.     /********* no need to disable since we never enable
  18724.     if (@queued_pub = 1)
  18725.     begin
  18726.         --
  18727.         -- disable loopback for queued
  18728.         --
  18729.         select @cmd = N'
  18730.     else if (@execution_mode in (@QFirstPass, @QSubWins))
  18731.     begin
  18732.         ' + N'--
  18733.         ' + N'-- For queued
  18734.         ' + N'-- disable loopback detection
  18735.         ' + N'--
  18736.         exec @retcode = dbo.sp_replsetoriginator N''anull'', N''anull''
  18737.         if (@retcode != 0 or @@error != 0) 
  18738.             return -1
  18739.     end'
  18740.         insert into #proctext(procedure_text) values( @cmd )
  18741.     end
  18742.     **********/
  18743.  
  18744.     if (@queued_pub = 1)
  18745.     begin
  18746.         --
  18747.         -- Queued reinitialization mode execution
  18748.         --
  18749.         select @cmd = N'
  18750.     else if (@execution_mode = @QReinit)
  18751.     begin
  18752.         ' + N'--
  18753.         ' + N'-- For Queued reinitialization
  18754.         ' + N'-- Set the Queue and subscription for reinit
  18755.         ' + N'--'
  18756.         insert into #proctext(procedure_text) values( @cmd )
  18757.  
  18758.         select @cmd = N'
  18759.         exec @retcode = dbo.sp_reinitsubscription @publication = ''' 
  18760.             + master.dbo.fn_MSgensqescstr(@publication) collate database_default + N''', @article = ''' +  
  18761.             master.dbo.fn_MSgensqescstr(@article) collate database_default + N''', @subscriber = @orig_server, @destination_db = @orig_db
  18762.         if (@retcode != 0 or @@error != 0)
  18763.             return -1
  18764.         else
  18765.             return 0
  18766.     end'
  18767.  
  18768.         insert into #proctext(procedure_text) values( @cmd )
  18769.     end
  18770.  
  18771.     --
  18772.     -- all done
  18773.     --
  18774.     return 0
  18775. end 
  18776. go
  18777. EXEC dbo.sp_MS_marksystemobject sp_MSscript_ExecutionMode_stmt
  18778. GO
  18779.  
  18780. raiserror('Creating procedure sp_MSscript_sync_ins_proc', 0,1)
  18781. go
  18782. create procedure sp_MSscript_sync_ins_proc (
  18783.     @publication sysname, 
  18784.     @article     sysname,
  18785.     @procname    sysname)
  18786. as
  18787. BEGIN
  18788.     declare @source_objid int
  18789.             ,@colname sysname
  18790.             ,@indid int
  18791.             ,@cmd          nvarchar(4000)
  18792.             ,@columns      binary(32)
  18793.             ,@outvars      nvarchar(4000)
  18794.             ,@rc           int
  18795.             ,@error_cmd    tinyint
  18796.             ,@identity_insert bit
  18797.             ,@queued_pub bit
  18798.  
  18799.     set nocount on
  18800.     --
  18801.     -- Create temp table
  18802.     --
  18803.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  18804.     select @queued_pub = allow_queued_tran from syspublications where name = @publication
  18805.  
  18806.     --
  18807.     -- proc definition
  18808.     --
  18809.     exec @rc = dbo.sp_MSscript_beginproc @publication, @article, @procname, @source_objid output, @columns output
  18810.     if @rc = 0
  18811.         return
  18812.  
  18813.     --
  18814.     -- construct parameter list
  18815.     --
  18816.     exec dbo.sp_MSscript_params @source_objid, @columns, null, 1,  @outvars output
  18817.  
  18818.     --
  18819.     -- add other parameters and start body of proc
  18820.     --
  18821.     exec dbo.sp_MSscript_procbodystart @queued_pub
  18822.  
  18823.     --
  18824.     -- script out security check
  18825.     --
  18826.     exec dbo.sp_MSscript_security @publication
  18827.  
  18828.     --
  18829.     -- script the execution mode checks
  18830.     --
  18831.     exec dbo.sp_MSscript_ExecutionMode_stmt @publication, @article, 0
  18832.  
  18833.     --
  18834.     -- script out subscription validation
  18835.     --
  18836.     exec dbo.sp_MSscript_validate_subscription @publication, @article
  18837.  
  18838.     --
  18839.     -- Work around for case where article has 1 col that is not user-modfied (identity, timestamp)
  18840.     -- *** Do we need to check this here - 
  18841.     -- *** we should be checking this when creating subscription
  18842.     -- 
  18843.     exec @rc = dbo.sp_MStable_not_modifiable @source_objid, @columns
  18844.     if @rc = 1
  18845.         select @error_cmd = 1
  18846.     else
  18847.     begin
  18848.         exec @indid = dbo.sp_MStable_has_unique_index @source_objid 
  18849.         if (@outvars != null and @indid = 0)
  18850.             -- no insert/update allowed if timestamp/identity col and no unique index
  18851.             select @error_cmd = 1
  18852.         else
  18853.             select @error_cmd = 0        
  18854.     end
  18855.  
  18856.     if (@error_cmd = 0)
  18857.     begin
  18858.         -- Continue generation
  18859.     
  18860.         -- Check to see if identity insert must be turned on
  18861.         -- i.e. Does the table has identity that are included in the partition?
  18862.         exec sp_MSis_identity_insert @publication, @article, @identity_insert output
  18863.         --
  18864.         -- script insert statemnt
  18865.         --
  18866.         exec dbo.sp_MSscript_insert_statement @source_objid, @columns, @identity_insert, @queued_pub
  18867.  
  18868.         --
  18869.         -- script queued specific stuff
  18870.         --
  18871.         if (@queued_pub = 1)
  18872.         begin
  18873.             --
  18874.             -- script Conflict resolution block for Subscriber Wins case
  18875.             --
  18876.             exec dbo.sp_MSscript_insert_subwins @publication, @article, @source_objid, @columns, @identity_insert
  18877.  
  18878.             --
  18879.             -- script Conflict resolution block for Publisher Wins case
  18880.             --
  18881.             exec dbo.sp_MSscript_insert_pubwins @publication, @article, @source_objid, @columns
  18882.         end
  18883.         
  18884.         --
  18885.         -- script closing 
  18886.         --
  18887.         exec dbo.sp_MSscript_endproc @source_objid, 'ins', @columns, @outvars, @queued_pub
  18888.     end
  18889.     else
  18890.     begin
  18891.         --
  18892.         -- Generate error command and finish
  18893.         --
  18894.         insert into #proctext(procedure_text) values( N'
  18895.     exec sp_MSreplraiserror 20516
  18896. END
  18897. ')
  18898.     end
  18899.                   
  18900.     --
  18901.     -- send fragments to client
  18902.     --
  18903.     select procedure_text from #proctext order by c1 asc
  18904. END
  18905. go
  18906.  
  18907. EXEC dbo.sp_MS_marksystemobject sp_MSscript_sync_ins_proc
  18908. GO
  18909.  
  18910. raiserror('Creating procedure sp_MSscript_sync_upd_proc', 0,1)
  18911. go
  18912. create procedure sp_MSscript_sync_upd_proc (
  18913.     @publication sysname, 
  18914.     @article     sysname,
  18915.     @procname    sysname)
  18916. as
  18917. BEGIN
  18918.     declare @source_objid int
  18919.             ,@colname sysname
  18920.             ,@indid int
  18921.             ,@cmd          nvarchar(4000)
  18922.             ,@columns      binary(32)
  18923.             ,@outvars      nvarchar(4000)
  18924.             ,@rc           int
  18925.             ,@error_cmd    tinyint
  18926.             ,@identity_insert bit
  18927.             ,@queued_pub bit
  18928.  
  18929.     set nocount on
  18930.     --
  18931.     -- Create temp table
  18932.     --
  18933.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  18934.     select @queued_pub = allow_queued_tran from syspublications where name = @publication
  18935.  
  18936.     --
  18937.     -- proc definition
  18938.     --
  18939.     exec @rc = dbo.sp_MSscript_beginproc @publication, @article, @procname, @source_objid output, @columns output
  18940.     if @rc = 0
  18941.         return
  18942.  
  18943.     --
  18944.     -- construct parameter list
  18945.     -- Script bitmap parameter
  18946.     --
  18947.     exec dbo.sp_MSscript_params @source_objid, @columns, null, 1,  @outvars output
  18948.     insert into #proctext(procedure_text) values( N',')
  18949.     exec dbo.sp_MSscript_params @source_objid, @columns, N'_old', 0, null
  18950.     insert into #proctext(procedure_text) values( N'
  18951.     ,@bitmap varbinary(4000)')
  18952.  
  18953.     --
  18954.     -- add other parameters and start body of proc
  18955.     --
  18956.     exec dbo.sp_MSscript_procbodystart @queued_pub 
  18957.  
  18958.     --
  18959.     -- script out security check
  18960.     --
  18961.     exec dbo.sp_MSscript_security @publication
  18962.  
  18963.     --
  18964.     -- script the execution mode checks
  18965.     --
  18966.     exec dbo.sp_MSscript_ExecutionMode_stmt @publication, @article, 2
  18967.  
  18968.     --
  18969.     -- script out subscription validation
  18970.     --
  18971.     exec dbo.sp_MSscript_validate_subscription @publication, @article
  18972.  
  18973.     --
  18974.     -- Work around for case where article has 1 col that is not user-modfied (identity, timestamp)
  18975.     -- *** Do we need to check this here - 
  18976.     -- *** we should be checking this when creating subscription
  18977.     -- 
  18978.     exec @rc = dbo.sp_MStable_not_modifiable @source_objid, @columns
  18979.     if @rc = 1
  18980.         select @error_cmd = 1
  18981.     else
  18982.     begin
  18983.         exec @indid = dbo.sp_MStable_has_unique_index @source_objid 
  18984.         if (@outvars != null and @indid = 0)
  18985.             -- no insert/update allowed if timestamp/identity col and no unique index
  18986.             select @error_cmd = 1
  18987.         else
  18988.             select @error_cmd = 0        
  18989.     end
  18990.  
  18991.     if (@error_cmd = 0)
  18992.     begin
  18993.         -- Continue generation
  18994.         
  18995.         --
  18996.         -- script update statemnt
  18997.         --
  18998.         exec dbo.sp_MSscript_update_statement @publication, @article, @source_objid, @columns, @queued_pub
  18999.  
  19000.         --
  19001.         -- script queued specific stuff
  19002.         --
  19003.         if (@queued_pub = 1)
  19004.         begin
  19005.             -- Check to see if identity insert must be turned on
  19006.             -- i.e. Does the table has identity that are included in the partition?
  19007.             exec sp_MSis_identity_insert @publication, @article, @identity_insert output
  19008.             --
  19009.             --
  19010.             -- script Conflict resolution block for Subscriber Wins case
  19011.             --
  19012.             exec dbo.sp_MSscript_update_subwins @publication, @article, @source_objid, @columns, @identity_insert
  19013.  
  19014.             --
  19015.             -- script Conflict resolution block for Publisher Wins case
  19016.             --
  19017.             exec dbo.sp_MSscript_update_pubwins @publication, @article, @source_objid, @columns
  19018.         end
  19019.  
  19020.         --
  19021.         -- script closing 
  19022.         --
  19023.         exec dbo.sp_MSscript_endproc @source_objid, 'upd', @columns, @outvars, @queued_pub
  19024.     end
  19025.     else
  19026.     begin
  19027.         --
  19028.         -- Generate error command and finish
  19029.         --
  19030.         insert into #proctext(procedure_text) values( N'
  19031.     exec sp_MSreplraiserror 20516
  19032. END
  19033. ')
  19034.     end
  19035.                   
  19036.     --
  19037.     -- send fragments to client
  19038.     --
  19039.     select procedure_text from #proctext order by c1 asc
  19040. END
  19041. go
  19042.  
  19043. EXEC dbo.sp_MS_marksystemobject sp_MSscript_sync_upd_proc
  19044. GO
  19045.  
  19046. raiserror('Creating procedure sp_MSscript_sync_del_proc', 0,1)
  19047. go
  19048. create procedure sp_MSscript_sync_del_proc (
  19049.     @publication sysname, 
  19050.     @article     sysname,
  19051.     @procname    sysname)
  19052. as
  19053. BEGIN
  19054.     declare @source_objid int
  19055.     declare @colname sysname
  19056.     declare @indid int
  19057.     declare @cmd          nvarchar(4000)
  19058.     declare @columns      binary(32)
  19059.     declare @outvars      nvarchar(4000)
  19060.     declare @rc           int
  19061.     declare @error_cmd    tinyint
  19062.     declare @queued_pub bit
  19063.  
  19064.     set nocount on
  19065.     --
  19066.     -- Create temp table
  19067.     --
  19068.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  19069.     select @queued_pub = allow_queued_tran from syspublications where name = @publication
  19070.  
  19071.     --
  19072.     -- proc definition
  19073.     --
  19074.     exec @rc = dbo.sp_MSscript_beginproc @publication, @article, @procname, @source_objid output, @columns output
  19075.     if @rc = 0
  19076.         return
  19077.  
  19078.     --
  19079.     -- construct parameter list
  19080.     --
  19081.     exec dbo.sp_MSscript_params @source_objid, @columns, N'_old', 0, null
  19082.  
  19083.     --
  19084.     -- add other parameters and start body of proc
  19085.     --
  19086.     exec dbo.sp_MSscript_procbodystart @queued_pub 
  19087.  
  19088.     --
  19089.     -- script out security check
  19090.     --
  19091.     exec dbo.sp_MSscript_security @publication
  19092.  
  19093.     --
  19094.     -- script the execution mode checks
  19095.     --
  19096.     exec dbo.sp_MSscript_ExecutionMode_stmt @publication, @article, 1
  19097.  
  19098.     --
  19099.     -- script out subscription validation
  19100.     --
  19101.     exec dbo.sp_MSscript_validate_subscription @publication, @article
  19102.  
  19103.     --
  19104.     -- Work around for case where article has 1 col that is not user-modfied (identity, timestamp)
  19105.     -- *** Do we need to check this here - 
  19106.     -- *** we should be checking this when creating subscription
  19107.     -- 
  19108.     exec @rc = dbo.sp_MStable_not_modifiable @source_objid, @columns
  19109.     if @rc = 1
  19110.         select @error_cmd = 1
  19111.     else
  19112.     begin
  19113.         exec @indid = dbo.sp_MStable_has_unique_index @source_objid 
  19114.         if (@outvars != null and @indid = 0)
  19115.             -- no insert/update allowed if timestamp/identity col and no unique index
  19116.             select @error_cmd = 1
  19117.         else
  19118.             select @error_cmd = 0        
  19119.     end
  19120.  
  19121.     if (@error_cmd = 0)
  19122.     begin
  19123.         -- Continue generation
  19124.         
  19125.         --
  19126.         -- script delete statemnt
  19127.         --
  19128.         exec dbo.sp_MSscript_delete_statement @publication, @article, @source_objid, @columns, @queued_pub
  19129.  
  19130.         --
  19131.         -- script queued specific stuff
  19132.         --
  19133.         if (@queued_pub = 1)
  19134.         begin
  19135.             --
  19136.             -- script Conflict resolution block for Subscriber Wins case
  19137.             --
  19138.             exec dbo.sp_MSscript_delete_subwins @publication, @article, @source_objid, @columns
  19139.  
  19140.             --
  19141.             -- script Conflict resolution block for Publisher Wins case
  19142.             --
  19143.             exec dbo.sp_MSscript_delete_pubwins @publication, @article, @source_objid, @columns
  19144.         end
  19145.         
  19146.         --
  19147.         -- script closing 
  19148.         --
  19149.         exec dbo.sp_MSscript_endproc @source_objid, 'del', @columns, @outvars, @queued_pub
  19150.     end
  19151.     else
  19152.     begin
  19153.         --
  19154.         -- Generate error command and finish
  19155.         --
  19156.         insert into #proctext(procedure_text) values( N'
  19157.     exec sp_MSreplraiserror 20516
  19158. END
  19159. ')
  19160.     end
  19161.                   
  19162.     --
  19163.     -- send fragments to client
  19164.     --
  19165.     select procedure_text from #proctext order by c1 asc
  19166.  
  19167. END
  19168. go
  19169.  
  19170. EXEC dbo.sp_MS_marksystemobject sp_MSscript_sync_del_proc
  19171. GO
  19172.  
  19173. raiserror('Creating procedure sp_MSscript_pub_upd_trig', 0,1)
  19174. go
  19175. create procedure sp_MSscript_pub_upd_trig
  19176.     @publication sysname, 
  19177.     @article     sysname,
  19178.     @procname    sysname
  19179. as
  19180.     declare @cmd       nvarchar(4000)
  19181.     declare @qualname  nvarchar(512)
  19182.     declare @objid       int
  19183.     declare @columns   binary(32)
  19184.  
  19185.     set nocount on
  19186.  
  19187.     -- Create temp table
  19188.     create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  19189.  
  19190.  
  19191.     -- Retrieve underlying table name and replicated columns
  19192.     select @objid = objid, @columns = columns from sysarticles a, syspublications p
  19193.         where a.name = @article and
  19194.               p.name = @publication and
  19195.               a.pubid = p.pubid
  19196.  
  19197.     exec sp_MSget_qualified_name @objid, @qualname OUTPUT
  19198.  
  19199.     -- Trigger should be invoked for repl processes as well.
  19200.     select @cmd = N'create trigger ' + QUOTENAME(@procname) + N' on ' + @qualname + N' '
  19201.     select @cmd = @cmd + N'for update as ' 
  19202.  
  19203.     exec dbo.sp_MSflush_command @cmd output, 1
  19204.  
  19205.     insert into #proctext(procedure_text) values(N'
  19206. ')
  19207.     -- declare common local variables
  19208.     insert into #proctext(procedure_text) values 
  19209.         (N'declare @rc int
  19210. ')
  19211.     insert into #proctext(procedure_text) values(N'select @rc = @@ROWCOUNT 
  19212.  
  19213. ')
  19214.         
  19215.     -- Optimization. Return immediately if no row changed
  19216.     -- This must be at the beginning of the trigger to @@rowcount be overwritten.
  19217.     insert into #proctext(procedure_text) values(N'if @rc = 0 return 
  19218. ')
  19219.     insert into #proctext(procedure_text) values(N'if update (msrepl_tran_version) return 
  19220. ')
  19221.  
  19222.     -- update the version column of all the updated rows all at once.
  19223.     select @cmd = N'update ' + @qualname + N' set msrepl_tran_version = newid() from ' +
  19224.         @qualname + ', inserted '
  19225.     exec dbo.sp_MSflush_command @cmd output, 1
  19226.     insert into #proctext(procedure_text) values(N'
  19227. ')
  19228.     exec dbo.sp_MSscript_where_clause @objid, @columns, 'version pk', null, 4
  19229.  
  19230.     insert into #proctext(procedure_text) values(N'
  19231. ')
  19232.     -- send fragments to client
  19233.     select procedure_text from #proctext order by c1 asc
  19234. go
  19235. EXEC dbo.sp_MS_marksystemobject sp_MSscript_pub_upd_trig
  19236. go
  19237.  
  19238. raiserror('Creating procedure sp_MSmakeconflicttable', 0,1)
  19239. go
  19240. create procedure sp_MSmakeconflicttable (
  19241.     @article sysname, 
  19242.     @publication sysname,
  19243.     @creation_mode bit = 0,     -- 0 = for publisher, 1 = for subscriber (snapshot)
  19244.     @is_debug bit = 0)    
  19245. as
  19246. begin
  19247.     --
  19248.     -- variables
  19249.     --
  19250.     declare @retcode    int
  19251.             ,@cmd        nvarchar(4000)
  19252.             ,@qualname    sysname
  19253.             ,@basetablename nvarchar(540)
  19254.             ,@id         int
  19255.             ,@colid        int
  19256.             ,@colname    sysname
  19257.             ,@col        sysname
  19258.             ,@coltype    sysname
  19259.             ,@iscolnullable    bit
  19260.             ,@dbname        sysname
  19261.             ,@ownername    sysname
  19262.             ,@tablename    sysname
  19263.             ,@basetableid int
  19264.             ,@columns    varbinary(32)
  19265.             ,@isset        int
  19266.             ,@tabid        int
  19267.             ,@artid        int
  19268.             ,@pubid        int
  19269.             ,@indid        int
  19270.             ,@indkey        int
  19271.             ,@key        sysname
  19272.             ,@indexname    sysname
  19273.             ,@mode_publisher bit
  19274.             ,@mode_subscriber bit
  19275.             ,@is_queued bit
  19276.  
  19277.     set nocount on
  19278.     select @dbname = db_name()
  19279.     select @mode_publisher = 0, @mode_subscriber = 1
  19280.  
  19281.     --
  19282.     -- Check and make sure the base table exists
  19283.     --
  19284.     select    @artid = a.artid, @basetableid = a.objid, 
  19285.             @basetablename = object_name(a.objid), @columns = a.columns, 
  19286.             @pubid = a.pubid, @is_queued = NULLIF(p.allow_queued_tran, 0)
  19287.     from sysarticles a, syspublications p
  19288.     where    a.name = @article and
  19289.             p.name = @publication and
  19290.             a.pubid = p.pubid
  19291.     if (@basetableid is null or @basetableid = 0)
  19292.     begin
  19293.         raiserror('sp_MSmakeconflicttable(debug): bad basetableid = %d', 16, 1, @basetableid)
  19294.         return (1)
  19295.     end
  19296.  
  19297.     --
  19298.     -- If the publication does not allowed queued tran, return
  19299.     --
  19300.     if (@is_queued != 1)
  19301.         return 0
  19302.  
  19303.     --
  19304.     -- get the article owner
  19305.     --
  19306.     select @ownername = user_name(o.uid) 
  19307.     from sysobjects o , sysarticles a 
  19308.     where    o.id=a.objid and 
  19309.             a.name=@article
  19310.  
  19311.     --
  19312.     -- base table should be owner qualified
  19313.     --
  19314.     select @basetablename = QUOTENAME(@ownername) + N'.' + QUOTENAME(@basetablename)
  19315.     
  19316.     --
  19317.     -- Prepare the name for the Conflict table, index
  19318.     --
  19319.     if (@creation_mode = @mode_publisher)
  19320.     begin
  19321.         --
  19322.         -- creating on publisher - get unique names for table, index
  19323.         --
  19324.         exec @retcode = sp_MSgettranconflictname @publication=@publication, 
  19325.                             @source_object=@basetablename, 
  19326.                             @str_prefix='conflict_', 
  19327.                             @conflict_table=@tablename OUTPUT
  19328.         if (@retcode != 0 or @@error != 0)
  19329.         begin
  19330.             raiserror('sp_MSmakeconflicttable(debug): sp_MSgettranconflictname failed for cft name', 16, 1)
  19331.             return (1)
  19332.         end
  19333.  
  19334.         exec @retcode = sp_MSgettranconflictname @publication=@publication, 
  19335.                             @source_object=@basetablename, 
  19336.                             @str_prefix='cftind_', 
  19337.                             @conflict_table=@indexname OUTPUT
  19338.         if (@retcode != 0 or @@error != 0)
  19339.         begin
  19340.             raiserror('sp_MSmakeconflicttable(debug): sp_MSgettranconflictname failed for cft index', 16, 1)
  19341.             return (1)
  19342.         end
  19343.     end
  19344.     else
  19345.     begin
  19346.         --
  19347.         -- Get the destination owner
  19348.         --
  19349.         select    @ownername = dest_owner
  19350.         from sysarticles 
  19351.         where artid = @artid and pubid = @pubid
  19352.         
  19353.         --
  19354.         -- creating for subscriber, get the names from existing
  19355.         -- table on publisher
  19356.         --
  19357.         select @id = conflict_tableid, @tablename = OBJECT_NAME(conflict_tableid) 
  19358.         from sysarticleupdates
  19359.         where artid = @artid and pubid = @pubid
  19360.  
  19361.         exec @indid = dbo.sp_MStable_has_unique_index @id
  19362.         if (@indid = 0)
  19363.         begin
  19364.             raiserror('sp_MSmakeconflicttable(debug): no unique index for cft table', 16, 1)
  19365.             return (1)
  19366.         end
  19367.             
  19368.         select @indexname = name
  19369.         from sysindexes 
  19370.         where indid = @indid and id = @id
  19371.     end
  19372.     
  19373.     --
  19374.     -- Qualify the Conflict tablename
  19375.     --
  19376.     select @qualname = case 
  19377.         when (@ownername is null or @ownername = ' ') then QUOTENAME(@tablename)
  19378.                 else QUOTENAME(@ownername) + '.' + QUOTENAME(@tablename) end
  19379.  
  19380.     --
  19381.     -- To check if specified object exists in current database drop it if it exists
  19382.     -- Do this only if we are creating for Publisher
  19383.     --
  19384.     if (@creation_mode = @mode_publisher)
  19385.     begin
  19386.         select @id = object_id(@qualname)
  19387.         if @id is not NULL
  19388.         begin
  19389.             execute( N'drop table ' + @qualname )
  19390.             if (@@error != 0)
  19391.             begin
  19392.                 raiserror('sp_MSmakeconflicttable(debug): could not drop cft table', 16, 1)
  19393.                 return (1)
  19394.             end
  19395.         end
  19396.     end
  19397.  
  19398.     --
  19399.     -- begin tran
  19400.     --
  19401.     begin tran sp_MSmakeconflicttable
  19402.  
  19403.     --
  19404.     -- create table to select the command text out of
  19405.     --
  19406.     if exists (select * from sysobjects where name = 'tempcmd' and uid = user_id('dbo'))
  19407.         drop table dbo.tempcmd
  19408.         
  19409.     create table dbo.tempcmd (step int identity NOT NULL, cmdtext nvarchar(4000) NULL)
  19410.  
  19411.     if (@creation_mode = @mode_subscriber)
  19412.     begin
  19413.         select @cmd = N'DROP TABLE ' + @qualname + N'
  19414. '
  19415.         insert into dbo.tempcmd(cmdtext) values(@cmd)
  19416.         insert into dbo.tempcmd(cmdtext) values(N'GO
  19417. ')        
  19418.     end
  19419.     
  19420.     select @cmd = N'CREATE TABLE ' + @qualname + N'('
  19421.     insert into dbo.tempcmd(cmdtext) values(@cmd)
  19422.  
  19423.     --
  19424.     -- Declare the cursor to get info on each column of base table
  19425.     --
  19426.     declare #hcurColumnInfo cursor local FAST_FORWARD FOR
  19427.         select colid,
  19428.         isnullable
  19429.         from syscolumns
  19430.         where iscomputed = 0 and id=@basetableid 
  19431.         order by colid
  19432.     FOR READ ONLY
  19433.  
  19434.     select @cmd = NULL
  19435.     open #hcurColumnInfo
  19436.     fetch #hcurColumnInfo into @colid, @iscolnullable
  19437.     while (@@FETCH_STATUS = 0)
  19438.     begin
  19439.         -- Check if this column is included for replication
  19440.         if (@columns is null)
  19441.             select @isset = 1
  19442.         else
  19443.             exec @isset = dbo.sp_isarticlecolbitset @colid, @columns
  19444.  
  19445.         -- Get the typestring for this column
  19446.         -- Skip this column if it is NULL
  19447.         if ( @isset != 0 )
  19448.         begin        
  19449.             exec @retcode = dbo.sp_MSget_type @basetableid, @colid, @colname output, @coltype OUTPUT
  19450.             if (@@ERROR!= 0 or @retcode != 0)
  19451.             begin
  19452.                 raiserror('sp_MSmakeconflicttable(debug): sp_MSget_type failed', 16, 1)
  19453.                 rollback tran sp_MSmakeconflicttable
  19454.                 return (1)
  19455.             end
  19456.  
  19457.             if (@coltype IS NULL)
  19458.                 select @isset = 0
  19459.         end
  19460.             
  19461.         -- process the column ?
  19462.         if ( @isset != 0 )
  19463.         begin        
  19464.             -- Initialize
  19465.             if (@cmd is NULL)
  19466.                 select @cmd = N'    '
  19467.             else
  19468.                 select @cmd = N'    ,'
  19469.  
  19470.             -- Create the column info
  19471.             select @cmd = @cmd + quotename(@colname) + N' ' 
  19472.             select @cmd = @cmd + @coltype
  19473.             
  19474.             -- Apply nullability
  19475.             if (@iscolnullable = 1)
  19476.                 select @cmd = @cmd + N' NULL'
  19477.             else
  19478.                 select @cmd = @cmd + N' NOT NULL'
  19479.  
  19480.             -- insert into the temptable
  19481.             insert into dbo.tempcmd(cmdtext) values(@cmd)
  19482.         end
  19483.  
  19484.         -- do the next fetch
  19485.         fetch #hcurColumnInfo into @colid, @iscolnullable
  19486.     end
  19487.  
  19488.     close #hcurColumnInfo
  19489.     deallocate #hcurColumnInfo
  19490.  
  19491.     --
  19492.     -- Now add the conflict related columns
  19493.     --
  19494.     insert into dbo.tempcmd(cmdtext) values(N'    ,origin_datasource nvarchar(255) NULL
  19495.     ,conflict_type int NULL
  19496.     ,reason_code int NULL
  19497.     ,reason_text nvarchar(720) NULL
  19498.     ,pubid int NULL
  19499.     ,tranid nvarchar(40) NULL
  19500.     ,insertdate datetime NOT NULL
  19501.     ,qcfttabrowid uniqueidentifier DEFAULT NEWID() NOT NULL)
  19502.     ')
  19503.  
  19504.     --
  19505.     -- Create an unique index - we add some more fields to the index of base table
  19506.     --
  19507.     exec @indid = dbo.sp_MStable_has_unique_index @basetableid
  19508.     if (@indid = 0)
  19509.     begin
  19510.         raiserror('sp_MSmakeconflicttable(debug): no unique index for base table', 16, 1)
  19511.         rollback tran sp_MSmakeconflicttable
  19512.         return (1)
  19513.     end
  19514.  
  19515.     if (@creation_mode = @mode_subscriber)
  19516.     begin
  19517.         insert into dbo.tempcmd(cmdtext) values(N'GO
  19518. ')        
  19519.     end
  19520.  
  19521.     insert into dbo.tempcmd(cmdtext) values(N'
  19522.     CREATE UNIQUE INDEX ' + quotename(@indexname) + ' ON ' +  @qualname  + N'(')
  19523.  
  19524.     select @cmd = NULL
  19525.     select @indkey = 1
  19526.     while (@indkey <= 16)
  19527.     begin    
  19528.         select @key = index_col(@basetablename, @indid, @indkey)
  19529.         if (@key is not null)
  19530.         begin
  19531.             -- make sure we are replicating this column
  19532.             if (@columns is null)
  19533.                 select @isset = 1
  19534.             else
  19535.             begin
  19536.                 -- map the index to the right column in base table
  19537.                 exec dbo.sp_MSget_col_position @basetableid, @columns, @key, @col output, @colid output
  19538.                 exec @isset = dbo.sp_isarticlecolbitset @colid, @columns
  19539.             end
  19540.                 
  19541.             if (@isset = 1)
  19542.             begin
  19543.                 if (@cmd is NULL)
  19544.                     select @cmd = quotename(@key)
  19545.                 else
  19546.                     select @cmd = @cmd + N', ' + quotename(@key)
  19547.             end
  19548.         end
  19549.         select @indkey = @indkey + 1
  19550.     end
  19551.     
  19552.     --
  19553.     -- Add two more fields in the index
  19554.     --
  19555.     if (@cmd is NULL)
  19556.         select @cmd = N'tranid, qcfttabrowid'
  19557.     else
  19558.         select @cmd = @cmd + N', tranid, qcfttabrowid'
  19559.     insert into dbo.tempcmd(cmdtext) values(@cmd + N')')
  19560.  
  19561.     --
  19562.     -- If we are creating on publisher
  19563.     -- create the table now and update sysarticleupdates now
  19564.     --
  19565.     if (@creation_mode = @mode_publisher)
  19566.     begin
  19567.         if (@is_debug = 0)
  19568.         begin
  19569.             --
  19570.             -- create the table now
  19571.             --
  19572.             select @cmd = 'select cmdtext from dbo.tempcmd order by step'
  19573.             exec @retcode = master..xp_execresultset @cmd, @dbname
  19574.             if (@@error != 0 or @retcode != 0)
  19575.             begin
  19576.                 raiserror('sp_MSmakeconflicttable(debug): xp_execresultset failed', 16, 1)
  19577.                 rollback tran sp_MSmakeconflicttable
  19578.                 return (1)
  19579.             end
  19580.  
  19581.             --
  19582.             -- update sysarticleupdates
  19583.             --
  19584.             select @tabid = id from sysobjects where name = @tablename
  19585.             if (@tabid = 0 or @tabid is NULL)
  19586.             begin
  19587.                 raiserror('sp_MSmakeconflicttable(debug): cft table not created after xp_execresultset', 16, 1)
  19588.                 rollback tran sp_MSmakeconflicttable
  19589.                 return (1)
  19590.             end
  19591.             else
  19592.             begin
  19593.                 update dbo.sysarticleupdates set conflict_tableid = @tabid
  19594.                     where artid = @artid and pubid = @pubid
  19595.  
  19596.                 -- mark the table as system object
  19597.                 if (@ownername in ('dbo','INFORMATION_SCHEMA'))
  19598.                 begin
  19599.                     exec @retcode = dbo.sp_MS_marksystemobject @tablename
  19600.                     if (@@error != 0 or @retcode != 0)
  19601.                     begin
  19602.                         -- roll back the tran
  19603.                         raiserror('sp_MSmakeconflicttable(debug): sp_MS_marksystemobject exec failed for cft table', 16, 1)
  19604.                         rollback tran sp_MSmakeconflicttable
  19605.                         return (1)
  19606.                     end
  19607.                 end
  19608.             end
  19609.         end
  19610.         else
  19611.             select cmdtext from dbo.tempcmd order by step
  19612.     end
  19613.  
  19614.     --
  19615.     -- commit the tran
  19616.     --
  19617.     commit tran    
  19618.  
  19619.     --
  19620.     -- If we are creating for subscriber then
  19621.     -- just to a select on the temp table
  19622.     --
  19623.     if (@creation_mode = @mode_subscriber)
  19624.     begin
  19625.         select cmdtext from dbo.tempcmd order by step
  19626.     end
  19627.  
  19628.     -- drop the table we created
  19629.     drop table dbo.tempcmd
  19630.     return 0
  19631. end
  19632. go
  19633. exec dbo.sp_MS_marksystemobject sp_MSmakeconflicttable 
  19634. go
  19635.  
  19636. dump tran master with no_log
  19637. go
  19638.  
  19639. --
  19640. -- sp_scriptsubconflicttable
  19641. --
  19642. -- This proc is used when the user is creating a nosync queued subscription.
  19643. -- It generates the script for creating conflict table on subscriber for a 
  19644. -- given queued subscription article. The SP is executed on the publisher.publisher_db 
  19645. -- and it generates the script which is executed on the subscriber.subscriber_db
  19646. -- See the docs for more information on creation of nosync queued subscription.
  19647. -- 
  19648. -- Parameters:
  19649. --    @publication    sysname - name of publication we are subscribing to
  19650. --    @article    sysname - name of the subscribed article
  19651. --
  19652. -- Return :
  19653. --    0 if successfull, 1 otherwise
  19654. --
  19655. -- Rowset
  19656. --    Return script to create the conflict table for the given article
  19657. --
  19658. print ''
  19659. print 'Creating procedure sp_scriptsubconflicttable'
  19660. go
  19661. create proc sp_scriptsubconflicttable (
  19662.     @publication sysname
  19663.     ,@article sysname
  19664.     )
  19665. as
  19666. begin
  19667.     declare @retcode int
  19668.  
  19669.     --
  19670.     -- Security Check.
  19671.     --
  19672.     exec @retcode = dbo.sp_MSreplcheck_publish
  19673.     if (@@error != 0 or @retcode != 0)
  19674.         return (1)
  19675.  
  19676.     --
  19677.     -- Parameter Check: @publication.
  19678.     -- The @publication cannot be NULL and must conform to the rules
  19679.     -- for identifiers.
  19680.     --
  19681.     if (@publication IS NULL)
  19682.     begin
  19683.         raiserror (14043, 16, 2, '@publication')
  19684.         return (1)
  19685.     end
  19686.     exec @retcode = dbo.sp_validname @publication
  19687.     if (@retcode != 0)
  19688.         return (1)
  19689.  
  19690.     --
  19691.     -- Parameter Check: @article.
  19692.     -- The @article cannot be NULL and must conform to the rules
  19693.     -- for identifiers.
  19694.     --    
  19695.     if @article IS NULL
  19696.     begin
  19697.         raiserror (14043, 16, 3, '@article')
  19698.         return (1)
  19699.     end
  19700.     exec @retcode = dbo.sp_MSreplcheck_name @article
  19701.     if (@@error != 0 or @retcode != 0)
  19702.         return (1)
  19703.  
  19704.     if LOWER(@article) = 'all'
  19705.     begin
  19706.         raiserror (14032, 16, 2, '@article')
  19707.         return (1)
  19708.     end
  19709.  
  19710.     --
  19711.     -- now call the SP to generate the script
  19712.     --
  19713.     exec @retcode = dbo.sp_MSmakeconflicttable @article, @publication, 1
  19714.     return @retcode
  19715. end
  19716. go
  19717.  
  19718. EXEC dbo.sp_MS_marksystemobject sp_scriptsubconflicttable
  19719. GO
  19720.  
  19721. print ''
  19722. print 'Creating procedure sp_MSgen_sync_tran_procs'
  19723. go
  19724. create procedure sp_MSgen_sync_tran_procs (
  19725.     @publication    sysname,        -- table name 
  19726.     @article        sysname,
  19727.     @ins_proc       sysname,
  19728.     @upd_proc       sysname,
  19729.     @del_proc       sysname,
  19730.     @upd_trig        sysname
  19731. )
  19732. as
  19733. begin
  19734.     set nocount on
  19735.  
  19736.     declare @cmd nvarchar(4000)
  19737.             ,@procname nvarchar(517)
  19738.             ,@dbname sysname
  19739.             ,@owner sysname
  19740.             ,@retcode int
  19741.  
  19742.     select @owner = user_name(o.uid) from sysobjects o , sysarticles a where o.id=a.objid and a.name=@article
  19743.  
  19744.     -- We are now going to create procs, so start a transaction
  19745.     begin tran gen_procs
  19746.         
  19747.         -- Call out to individual create proc routines      
  19748.         select @dbname = db_name()
  19749.         select @cmd = N'sp_MSscript_sync_ins_proc ''' + master.dbo.fn_MSgensqescstr(@publication) collate database_default + 
  19750.                 N''', ''' + master.dbo.fn_MSgensqescstr(@article) collate database_default  + 
  19751.                 N''', ''' + master.dbo.fn_MSgensqescstr(@ins_proc) collate database_default + N''''
  19752.         exec @retcode = master.dbo.xp_execresultset @cmd, @dbname
  19753.         if (@@error != 0 or @retcode != 0)
  19754.         begin
  19755.             rollback tran gen_procs
  19756.             return 1
  19757.         end
  19758.  
  19759.         select @cmd = N'sp_MSscript_sync_upd_proc ''' + master.dbo.fn_MSgensqescstr(@publication) collate database_default + 
  19760.                 N''', ''' + master.dbo.fn_MSgensqescstr(@article) collate database_default + 
  19761.                 N''', ''' + master.dbo.fn_MSgensqescstr(@upd_proc) collate database_default + N''''
  19762.         exec @retcode = master.dbo.xp_execresultset @cmd, @dbname
  19763.         if (@@error != 0 or @retcode != 0)
  19764.         begin
  19765.             rollback tran gen_procs
  19766.             return 1
  19767.         end
  19768.  
  19769.         select @cmd = N'sp_MSscript_sync_del_proc ''' + master.dbo.fn_MSgensqescstr(@publication) collate database_default + 
  19770.                 N''', ''' + master.dbo.fn_MSgensqescstr(@article) collate database_default  + 
  19771.                 N''', ''' + master.dbo.fn_MSgensqescstr(@del_proc) collate database_default + N''''
  19772.         exec @retcode = master.dbo.xp_execresultset @cmd, @dbname
  19773.         if (@@error != 0 or @retcode != 0)
  19774.         begin
  19775.             rollback tran gen_procs
  19776.             return 1
  19777.         end
  19778.  
  19779.         select @cmd = N'sp_MSscript_pub_upd_trig ''' + master.dbo.fn_MSgensqescstr(@publication) collate database_default + 
  19780.                 N''', ''' + master.dbo.fn_MSgensqescstr(@article) collate database_default  + 
  19781.                 N''', ''' + master.dbo.fn_MSgensqescstr(@upd_trig) collate database_default + N''''
  19782.         exec @retcode = master.dbo.xp_execresultset @cmd, @dbname
  19783.         if (@@error != 0 or @retcode != 0)
  19784.         begin
  19785.             rollback tran gen_procs
  19786.             return 1
  19787.         end
  19788.  
  19789.         -- Grant permissions
  19790.         select @cmd = 'grant exec on ' + quotename(@owner) + '.' + quotename(@ins_proc) + ' to public'
  19791.         exec (@cmd)
  19792.         if (@@error != 0)
  19793.         begin
  19794.             rollback tran gen_procs
  19795.             return 1
  19796.         end
  19797.         select @cmd = 'grant exec on ' + quotename(@owner) + '.' + quotename(@upd_proc) + ' to public'
  19798.         exec (@cmd)
  19799.         if (@@error != 0)
  19800.         begin
  19801.             rollback tran gen_procs
  19802.             return 1
  19803.         end
  19804.         select @cmd = 'grant exec on ' + quotename(@owner) + '.' + quotename(@del_proc) + ' to public'
  19805.         exec (@cmd)
  19806.         if (@@error != 0)
  19807.         begin
  19808.             rollback tran gen_procs
  19809.             return 1
  19810.         end
  19811.  
  19812.         -- Mark procedures as system procs so they don't show up in the UI
  19813.         if @owner in ('dbo','INFORMATION_SCHEMA')
  19814.         begin
  19815.             select @procname = @owner + '.' + @ins_proc
  19816.             exec @retcode = dbo.sp_MS_marksystemobject @procname
  19817.             if (@@error != 0 or @retcode != 0)
  19818.             begin
  19819.                 rollback tran gen_procs
  19820.                 return 1
  19821.             end
  19822.             select @procname = @owner + '.' + @upd_proc
  19823.             exec @retcode = dbo.sp_MS_marksystemobject @procname
  19824.             if (@@error != 0 or @retcode != 0)
  19825.             begin
  19826.                 rollback tran gen_procs
  19827.                 return 1
  19828.             end
  19829.             select @procname = @owner + '.' + @del_proc
  19830.             exec @retcode = dbo.sp_MS_marksystemobject @procname
  19831.             if (@@error != 0 or @retcode != 0)
  19832.             begin
  19833.                 rollback tran gen_procs
  19834.                 return 1
  19835.             end
  19836.             select @procname = @owner + '.' + @upd_trig
  19837.             exec @retcode = dbo.sp_MS_marksystemobject @procname
  19838.             if (@@error != 0 or @retcode != 0)
  19839.             begin
  19840.                 rollback tran gen_procs
  19841.                 return 1
  19842.             end
  19843.         end
  19844.  
  19845.         -- Mark procedures to set 'NOT FOR REPL' bit
  19846.         select @procname = @owner + '.' + @ins_proc
  19847.         exec @retcode = dbo.sp_MSmark_proc_norepl @procname
  19848.         if (@@error != 0 or @retcode != 0)
  19849.         begin
  19850.             rollback tran gen_procs
  19851.             return 1
  19852.         end
  19853.         select @procname = @owner + '.' + @upd_proc
  19854.         exec @retcode = dbo.sp_MSmark_proc_norepl @procname
  19855.         if (@@error != 0 or @retcode != 0)
  19856.         begin
  19857.             rollback tran gen_procs
  19858.             return 1
  19859.         end
  19860.         select @procname = @owner + '.' + @del_proc
  19861.         exec @retcode = dbo.sp_MSmark_proc_norepl @procname
  19862.         if (@@error != 0 or @retcode != 0)
  19863.         begin
  19864.             rollback tran gen_procs
  19865.             return 1
  19866.         end
  19867.  
  19868.     -- Commit tran
  19869.     commit tran
  19870. end
  19871. go
  19872.  
  19873. EXEC dbo.sp_MS_marksystemobject sp_MSgen_sync_tran_procs
  19874. GO
  19875.  
  19876. print ''
  19877. print 'Creating procedure sp_articlesynctranprocs'
  19878. go
  19879.  
  19880. CREATE PROCEDURE sp_articlesynctranprocs
  19881.     @publication sysname,         -- publication name 
  19882.     @article sysname,              -- article name 
  19883.     @ins_proc sysname,       -- name of sproc supporting Sync Tran inserts associated with this article
  19884.     @upd_proc sysname,       -- name of sproc supporting Sync Tran updates associated with this article
  19885.     @del_proc sysname,       -- name of sproc supporting Sync Tran deletes associated with this article
  19886.     @autogen       nvarchar(5) = 'true', -- indicates wether or not to auto generate sprocs
  19887.     @upd_trig sysname
  19888. AS
  19889.     SET NOCOUNT ON
  19890.  
  19891.     -- Declarations.
  19892.     DECLARE @pubid int
  19893.     DECLARE @artid int
  19894.     DECLARE @retcode int
  19895.     DECLARE @autogen_id bit
  19896.     DECLARE @ins_proc_id int
  19897.     DECLARE @upd_proc_id int
  19898.     DECLARE @del_proc_id int
  19899.     DECLARE @upd_trig_id int
  19900.     
  19901.     /* 
  19902.     ** Security Check.
  19903.     */
  19904.     exec @retcode = dbo.sp_MSreplcheck_publish
  19905.     if @@ERROR <> 0 or @retcode <> 0
  19906.         return(1)
  19907.     
  19908.     -- Parameter Check: @article. The @article name cannot be NULL and must conform 
  19909.     -- to the rules for identifiers.
  19910.     IF @article IS NULL
  19911.         BEGIN
  19912.             RAISERROR (14043, 16, -1, '@article')
  19913.             RETURN (1)
  19914.         END
  19915.  
  19916.     EXECUTE @retcode = dbo.sp_validname @article
  19917.     IF @retcode <> 0
  19918.         RETURN(1)
  19919.     
  19920.     -- Parameter Check: @publication.
  19921.     -- The @publication name cannot be NULL and must conform to the rules
  19922.     -- for identifiers.
  19923.     IF @publication IS NULL
  19924.         BEGIN
  19925.             RAISERROR (14043, 16, -1, '@publication')
  19926.             RETURN (1)
  19927.         END
  19928.  
  19929.     EXECUTE @retcode = dbo.sp_validname @publication
  19930.     IF @retcode <> 0
  19931.         RETURN (1)
  19932.  
  19933.     -- Parameter Check: @ins_proc, @upd_proc, @del_proc, @upd_trig
  19934.     -- The sproc names cannot be NULL and must conform to the rules
  19935.     -- for identifiers
  19936.  
  19937.     IF @ins_proc IS NULL
  19938.         BEGIN
  19939.             RAISERROR (14043, 16, -1, '@ins_proc')
  19940.             RETURN (1)
  19941.         END
  19942.  
  19943.     EXECUTE @retcode = dbo.sp_validname @ins_proc
  19944.     IF @retcode <> 0
  19945.         RETURN (1)
  19946.  
  19947.     IF @upd_proc IS NULL
  19948.         BEGIN
  19949.             RAISERROR (14043, 16, -1, '@upd_proc')
  19950.             RETURN (1)
  19951.         END
  19952.  
  19953.     EXECUTE @retcode = dbo.sp_validname @upd_proc
  19954.     IF @retcode <> 0
  19955.         RETURN (1)
  19956.  
  19957.     IF @del_proc IS NULL
  19958.         BEGIN
  19959.             RAISERROR (14043, 16, -1, '@del_proc')
  19960.             RETURN (1)
  19961.         END
  19962.  
  19963.     EXECUTE @retcode = dbo.sp_validname @del_proc
  19964.     IF @retcode <> 0
  19965.         RETURN (1)
  19966.  
  19967.     IF @upd_trig IS NULL
  19968.         BEGIN
  19969.             RAISERROR (14043, 16, -1, '@upd_trig')
  19970.             RETURN (1)
  19971.         END
  19972.  
  19973.     EXECUTE @retcode = dbo.sp_validname @upd_trig
  19974.     IF @retcode <> 0
  19975.         RETURN (1)
  19976.  
  19977.     -- Parameter Check:  @autogen
  19978.     IF @autogen IS NULL OR LOWER(@autogen) NOT IN ('true', 'false')
  19979.     BEGIN
  19980.         RAISERROR (14148, 16, -1, '@autogen')
  19981.         RETURN (1)
  19982.     END
  19983.  
  19984.     IF LOWER(@autogen) = 'true' 
  19985.         SELECT @autogen_id = 1
  19986.     ELSE 
  19987.         SELECT @autogen_id = 0
  19988.  
  19989.     -- Retrieve pubid & artid
  19990.     SELECT @pubid = a.pubid, @artid = a.artid 
  19991.     FROM sysarticles a, syspublications p
  19992.     WHERE p.name = @publication AND a.name = @article AND
  19993.         a.pubid = p.pubid
  19994.     IF @pubid IS NULL OR @artid IS NULL
  19995.     BEGIN
  19996.         if @pubid IS NULL RAISERROR (20026, 16, 1, @publication)
  19997.         if @artid IS NULL RAISERROR (20026, 16, 1, @publication)
  19998.         RETURN (1)
  19999.     END
  20000.  
  20001.        BEGIN TRAN sp_articlesynctranprocs
  20002.  
  20003.         -- if @autogen is true, generate the sprocs
  20004.         IF @autogen_id = 1
  20005.         BEGIN
  20006.             EXECUTE @retcode =  dbo.sp_MSgen_sync_tran_procs @publication, @article, 
  20007.                 @ins_proc, @upd_proc, @del_proc, @upd_trig
  20008.             IF @retcode <> 0
  20009.             BEGIN
  20010.                 IF @@TRANCOUNT <> 0
  20011.                     ROLLBACK tran sp_articlesynctranprocs
  20012.                 RETURN (1)
  20013.             END
  20014.         END
  20015.  
  20016.         --retrieve sproc id's, fail if they don't exist
  20017.         SELECT @ins_proc_id = id FROM sysobjects WHERE name = @ins_proc
  20018.         SELECT @upd_proc_id = id FROM sysobjects WHERE name = @upd_proc
  20019.         SELECT @del_proc_id = id FROM sysobjects WHERE name = @del_proc
  20020.         select @upd_trig_id = id FROM sysobjects WHERE name = @upd_trig
  20021.  
  20022.         IF (@ins_proc_id IS NULL) OR (@upd_proc_id IS NULL) OR (@del_proc_id IS NULL) OR
  20023.             (@upd_trig_id IS NULL)             
  20024.         BEGIN
  20025.             if @ins_proc_id IS NULL RAISERROR (20500, 16, 1, @ins_proc)
  20026.             if @upd_proc_id IS NULL RAISERROR (20500, 16, 1, @upd_proc)
  20027.             if @del_proc_id IS NULL RAISERROR (20500, 16, 1, @del_proc)
  20028.             if @upd_trig_id IS NULL RAISERROR (20500, 16, 1, @upd_trig)
  20029.             IF @@TRANCOUNT <> 0
  20030.                 ROLLBACK tran sp_articlesynctranprocs
  20031.             RETURN (1)
  20032.         END
  20033.  
  20034.         -- perform insert into sysarticleupdates
  20035.         -- need to mark this as a system table, so this sproc can live in master db
  20036.         INSERT sysarticleupdates(pubid, artid, sync_ins_proc, sync_upd_proc, sync_del_proc, autogen, sync_upd_trig)
  20037.             VALUES (@pubid, @artid, @ins_proc_id, @upd_proc_id, @del_proc_id, @autogen_id, @upd_trig_id)
  20038.  
  20039.         IF @@ERROR <> 0
  20040.             BEGIN
  20041.                 IF @@TRANCOUNT <> 0
  20042.                     ROLLBACK tran sp_articlesynctranprocs
  20043.                 RETURN (1)
  20044.             END
  20045.  
  20046.     COMMIT TRAN
  20047. go
  20048.  
  20049. EXEC dbo.sp_MS_marksystemobject sp_articlesynctranprocs
  20050. GO
  20051.  
  20052. print ''
  20053. print 'Creating procedure sp_reinitsubscription'
  20054. go
  20055.  
  20056. CREATE PROCEDURE sp_reinitsubscription (
  20057.     @publication sysname = 'all',    /* publication name */
  20058.     @article sysname = 'all',        /* article name */
  20059.     -- Force user to specify the subscriber name
  20060.     @subscriber sysname,             /* subscriber name */
  20061.     @destination_db sysname = 'all'   /* destination database name */
  20062.     ,@for_schema_change bit = 0
  20063. ) AS
  20064.  
  20065.     DECLARE @retcode int
  20066.     DECLARE @distributor sysname
  20067.     DECLARE @distribdb sysname
  20068.     declare @active tinyint
  20069.     declare @subscribed tinyint
  20070.     declare @automatic tinyint
  20071.     DECLARE @artid int
  20072.     DECLARE @distproc nvarchar (255)
  20073.     DECLARE @dbname sysname
  20074.     DECLARE @sub_ts binary(10) -- must be binary(10) type.
  20075.     DECLARE @sync_type tinyint
  20076.     DECLARE @immediate_sync bit
  20077.     DECLARE @subscription_type int
  20078.     DECLARE @push int
  20079.     DECLARE @pub sysname
  20080.     DECLARE @dest_db sysname
  20081.     DECLARE @sub_name sysname
  20082.     DECLARE @art_name sysname
  20083.     DECLARE @none tinyint
  20084.     declare @login_name sysname
  20085.  
  20086.  
  20087.   
  20088.     -- Initialization
  20089.     select @active = 2
  20090.     select @subscribed = 1
  20091.     select @dbname = DB_NAME()
  20092.     SELECT @none = 2            /* Const: synchronization type 'none' */
  20093.     SELECT @automatic = 1       /* Const: synchronization type 'automatic' */
  20094.     select @push = 0
  20095.  
  20096.     /* 
  20097.     ** Security Check.
  20098.     ** We use login_name stored in syssubscriptions to manage security 
  20099.     */
  20100.  
  20101.     /* Validate names */
  20102.  
  20103.     EXECUTE @retcode = dbo.sp_validname @publication
  20104.     IF @@ERROR <> 0 OR @retcode <> 0
  20105.         RETURN (1)
  20106.  
  20107.     /* article name can be a quoted name
  20108.     EXECUTE @retcode = dbo.sp_validname @article
  20109.     IF @@ERROR <> 0 OR @retcode <> 0
  20110.         RETURN (1)
  20111.     */
  20112.  
  20113.     -- Subscriber can be NULL
  20114.     IF @subscriber IS NOT NULL
  20115.     BEGIN
  20116.         EXECUTE @retcode = dbo.sp_validname @subscriber
  20117.         IF @@ERROR <> 0 OR @retcode <> 0
  20118.             RETURN (1)
  20119.  
  20120.         EXECUTE @retcode = dbo.sp_validname @destination_db
  20121.         IF @@ERROR <> 0 OR @retcode <> 0
  20122.             RETURN (1)
  20123.     END
  20124.  
  20125.     -- Replace 'all' with '%'
  20126.     if LOWER(@publication) = 'all'
  20127.         SELECT @publication = '%'
  20128.  
  20129.     if LOWER(@article) = 'all'
  20130.         SELECT @article = '%'
  20131.  
  20132.     if LOWER(@subscriber) = 'all'
  20133.         SELECT @subscriber = '%'
  20134.  
  20135.     if LOWER(@destination_db) = 'all'
  20136.         SELECT @destination_db = '%'
  20137.  
  20138.     /*
  20139.     ** Parameter Check:  @publication
  20140.     ** Check to make sure that the publication exists, that it's not NULL,
  20141.     ** and that it conforms to the rules for identifiers.
  20142.     */
  20143.     IF NOT EXISTS (SELECT * FROM syspublications WHERE name LIKE @publication)
  20144.         BEGIN
  20145.         IF @publication = '%'
  20146.                 RAISERROR (14008, 11, -1)
  20147.         ELSE
  20148.                 RAISERROR (20026, 11, -1, @publication)
  20149.         RETURN (1)
  20150.         END
  20151.  
  20152.     /*
  20153.     ** Parameter Check:  @article
  20154.     ** Check to make sure that the article exists, that it's not null,
  20155.     ** and that it conforms to the rules for identifiers.
  20156.     */
  20157.     IF NOT EXISTS (SELECT *
  20158.                      FROM sysextendedarticlesview a,
  20159.                           syspublications b
  20160.                 WHERE a.name LIKE @article
  20161.                       AND a.pubid = b.pubid
  20162.                       AND b.name LIKE @publication)
  20163.  
  20164.         BEGIN
  20165.         IF @article = '%'
  20166.                 RAISERROR (14009, 11, -1, @publication)
  20167.         ELSE
  20168.                 RAISERROR (20027, 11, -1, @article)
  20169.         RETURN (1)
  20170.         END
  20171.  
  20172.     -- Don't check subscriber and dest_db for virtual subscriptions
  20173.     IF @subscriber IS NOT NULL
  20174.     BEGIN    
  20175.         /*
  20176.         ** Parameter Check:  @subscriber
  20177.         ** Check to make sure that the subscriber exists
  20178.         */
  20179.         if @subscriber <> '%' select @subscriber = UPPER(@subscriber)
  20180.         
  20181.         IF NOT EXISTS (SELECT *
  20182.                          FROM master..sysservers
  20183.                         WHERE ((@subscriber = N'%') OR (UPPER(srvname) = UPPER(@subscriber) collate database_default))
  20184.                           AND (srvstatus & 4) <> 0)
  20185.  
  20186.             BEGIN
  20187.                 RAISERROR (14063, 11, -1)
  20188.                 RETURN (1)
  20189.             END
  20190.     END
  20191.  
  20192.     -- Wrong dest_db will be caught by the following query
  20193.  
  20194.     -- Check to make sure the subscription exists 
  20195.     IF  @publication <> '%' AND
  20196.         @subscriber <> '%' AND
  20197.  
  20198.         NOT EXISTS (SELECT *
  20199.           FROM syssubscriptions sub,
  20200.                sysextendedarticlesview art,
  20201.                syspublications pub,
  20202.                master..sysservers ss
  20203.          WHERE pub.name LIKE @publication collate database_default
  20204.            AND art.name LIKE @article collate database_default
  20205.            AND ((UPPER(ss.srvname) = UPPER(@subscriber) collate database_default
  20206.            AND sub.srvid = ss.srvid)
  20207.            OR (@subscriber is NULL 
  20208.            AND pub.allow_anonymous = 1))
  20209.            AND sub.artid = art.artid
  20210.            AND art.pubid = pub.pubid
  20211.            AND ((@destination_db = N'%') OR (sub.dest_db = @destination_db collate database_default)))
  20212.     BEGIN
  20213.         RAISERROR (14055, 16, -1)
  20214.         RETURN (1)
  20215.     END
  20216.  
  20217.     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  20218.                                        @distribdb = @distribdb OUTPUT
  20219.     IF @retcode <> 0 OR @@ERROR <> 0
  20220.         RETURN (1)
  20221.  
  20222.     IF @distribdb IS NULL OR @distributor IS NULL
  20223.     BEGIN
  20224.         RAISERROR (14071, 16, -1)
  20225.         RETURN (1)
  20226.     END
  20227.  
  20228.     DECLARE hCresyncsub CURSOR LOCAL FAST_FORWARD FOR
  20229.         -- non immediate_sync pubs
  20230.         SELECT pub.name,
  20231.                pub.immediate_sync,
  20232.                art.name,
  20233.                ss.srvname,
  20234.                sub.dest_db,
  20235.                sub.sync_type,
  20236.                sub.subscription_type,
  20237.                sub.login_name
  20238.           FROM syssubscriptions sub,
  20239.                sysextendedarticlesview art,
  20240.                syspublications pub,
  20241.                master..sysservers ss
  20242.          WHERE pub.name LIKE @publication
  20243.            AND art.name LIKE @article
  20244.            AND ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber) collate database_default))
  20245.            AND sub.srvid = ss.srvid
  20246.            AND sub.artid = art.artid
  20247.            AND art.pubid = pub.pubid
  20248.            AND ((@destination_db = N'%') OR (sub.dest_db = @destination_db collate database_default))
  20249.            AND sub.status = @active
  20250.            AND pub.immediate_sync = 0
  20251.         
  20252.         UNION
  20253.         -- Immediate_sync pubs
  20254.         SELECT DISTINCT
  20255.                pub.name,
  20256.                immediate_sync,
  20257.                -- If @article is '%', do publication level operation.
  20258.                -- otherwise, do article level
  20259.                case @article 
  20260.                     when '%' then '%'
  20261.                     else art.name
  20262.                     end, 
  20263.                ss.srvname,
  20264.                sub.dest_db,
  20265.                sub.sync_type,
  20266.                sub.subscription_type,
  20267.                sub.login_name
  20268.           FROM syssubscriptions sub,
  20269.                sysextendedarticlesview art,
  20270.                syspublications pub,
  20271.                master..sysservers ss
  20272.          WHERE pub.name LIKE @publication collate database_default -- Ignore @article
  20273.            AND art.name LIKE @article collate database_default
  20274.            AND ((@subscriber = N'%') OR (UPPER(ss.srvname) = UPPER(@subscriber) collate database_default))
  20275.            AND sub.srvid = ss.srvid
  20276.            AND sub.artid = art.artid
  20277.            AND art.pubid = pub.pubid
  20278.            AND ((@destination_db = N'%') OR (sub.dest_db = @destination_db collate database_default))
  20279.            AND sub.status = @active
  20280.            AND pub.immediate_sync = 1
  20281.                  
  20282.         UNION
  20283.         -- For anonymous subscribers or attached subscriptions.
  20284.         SELECT DISTINCT pub.name,
  20285.                immediate_sync,
  20286.                -- If @article is '%', do publication level operation.
  20287.                -- otherwise, do article level
  20288.                case @article 
  20289.                     when '%' then '%'
  20290.                     else art.name
  20291.                     end, -- art.name is '%' from immediate_sync pub
  20292.                CONVERT(sysname, NULL), -- subscriber name (null represent virtual)
  20293.                'virtual', -- destination_db for virtual subscription is hardcoded in 
  20294.                          -- sp_MSadd_subscription.
  20295.                @automatic, -- sub.sync_type is auto tor anonymous subscriber
  20296.                @push,      -- virtual subscription is push type,
  20297.                'sa'
  20298.           FROM syspublications pub,
  20299.                sysarticles art
  20300.          WHERE pub.name LIKE @publication -- Ignore @article
  20301.            AND art.name LIKE @article
  20302.            AND art.pubid = pub.pubid
  20303.            AND pub.immediate_sync = 1
  20304.            AND (@subscriber = '%' OR @subscriber IS NULL) 
  20305.                  
  20306.     FOR READ ONLY
  20307.  
  20308.     OPEN hCresyncsub 
  20309.  
  20310.     -- Note: Don't overwrite the variables used in the cursor.
  20311.     FETCH hCresyncsub INTO @pub, @immediate_sync, @art_name, @sub_name, 
  20312.         @dest_db, @sync_type, @subscription_type, @login_name
  20313.  
  20314.     WHILE (@@fetch_status <> -1)
  20315.     BEGIN
  20316.         -- Security Check
  20317.         IF  suser_sname(suser_sid()) <> @login_name AND is_srvrolemember('sysadmin') <> 1  
  20318.             AND is_member ('db_owner') <> 1
  20319.         BEGIN
  20320.                 RAISERROR (14126, 11, -1)
  20321.                 RETURN (1)
  20322.         END
  20323.  
  20324.         if @sync_type = @none
  20325.         begin
  20326.         raiserror(21071, 10, -1, @art_name, @sub_name, @dest_db, @pub)
  20327.         FETCH hCresyncsub INTO @pub, @immediate_sync, @art_name, @sub_name, 
  20328.             @dest_db, @sync_type, @subscription_type, @login_name
  20329.         continue
  20330.         end
  20331.  
  20332.         begin tran
  20333.         save TRAN sp_reinitsubscription
  20334.  
  20335.         -- Reset subscription status to subscribed.
  20336.         -- It will be reactivated later as following:
  20337.         -- 1. Well known on non immediate_sync: it need to be reactivated by snapshot agent
  20338.         -- 2. Well known on immediate_sync: it will be reactivated laster in 
  20339.         -- this stored procedure to the state of virtual subscription. The status will be 
  20340.         -- active if the virtual subscription is active.
  20341.         -- 3. Anonymous (on immediate_sync by design): Only reset the status to subscribed
  20342.         -- if a single article is reinited or there's a schema change on the article. 
  20343.         -- (refer to sp_MSreinit_article.) In this case, the status will be reactivated by
  20344.         -- snapshot agent. If the whole publication is reinited and it is not for a schema 
  20345.         -- change, we don't need to do this 
  20346.         -- since the anonymous agent will automatically pick up latest snapshots after
  20347.         -- we reset the subscription guid later.
  20348.  
  20349.         -- If @sub_name is null, we are resetting anonymous subscriptions.
  20350.         -- Don't do this when reiniting anonymous subscription on whole publication.
  20351.         IF not (@sub_name IS NULL and @article = '%') or @for_schema_change = 1
  20352.         BEGIN
  20353.             EXEC @retcode = dbo.sp_changesubstatus
  20354.                 @publication = @pub,
  20355.                 @article = @art_name,
  20356.                 @subscriber = @sub_name,
  20357.                 @destination_db = @dest_db,
  20358.                 @status = 'subscribed'
  20359.             IF @@ERROR <> 0 OR @retcode <> 0
  20360.             BEGIN
  20361.                 CLOSE hCresyncsub
  20362.                 DEALLOCATE hCresyncsub
  20363.                 RAISERROR (14070, 16, -1)
  20364.                 GOTO UNDO
  20365.             END
  20366.         END
  20367.  
  20368.         -- Don't do this when reiniting a single article.
  20369.         -- Reset the subscription guid at the distributor for immediate_sync publication.
  20370.          -- Reset subscription creation datetime for all types of publication
  20371.         -- used by retention cleanup.
  20372.         if @article = '%'
  20373.         begin
  20374.             SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSreset_subscription'
  20375.             EXEC @retcode = @distproc 
  20376.                 @publisher = @@SERVERNAME, 
  20377.                 @publisher_db = @dbname, 
  20378.                 @publication = @pub,
  20379.                 @subscriber = @sub_name, 
  20380.                 @subscriber_db = @dest_db,
  20381.                 @subscription_type = @subscription_type
  20382.  
  20383.             IF @@ERROR <> 0 OR @retcode <> 0
  20384.             BEGIN
  20385.                 CLOSE hCresyncsub
  20386.                 DEALLOCATE hCresyncsub
  20387.                 GOTO UNDO
  20388.             END
  20389.         end
  20390.  
  20391.         -- Activate the subscription again if the publication is immediate_sync and
  20392.         -- the whole publication is reinitted.
  20393.         -- Otherwise, the snapshot agent will activate the subscription
  20394.         
  20395.         -- If this is for schema change, commands generated by the LR will be invalid
  20396.         -- until the new snapshot is generated and applied so DON'T reactivate. 
  20397.         -- Let the snapshot agent do it.
  20398.  
  20399.         --IF (@for_schema_change = 0 AND @immediate_sync = 1 AND @subscriber IS NOT NULL)
  20400.         IF (@for_schema_change = 0 and 
  20401.                 @immediate_sync = 1 AND 
  20402.                 @subscriber IS NOT NULL and 
  20403.                 @article = '%')
  20404.         BEGIN
  20405.             -- Set subscription status back to active again.
  20406.             EXEC @retcode = dbo.sp_changesubstatus
  20407.                 @publication = @pub,
  20408.                 @article = @art_name,
  20409.                 @subscriber = @sub_name,
  20410.                 @destination_db = @dest_db,
  20411.                 @status = 'active'
  20412.             IF @@ERROR <> 0 OR @retcode <> 0
  20413.             BEGIN
  20414.                 CLOSE hCresyncsub
  20415.                 DEALLOCATE hCresyncsub
  20416.                 RAISERROR (14070, 16, -1)
  20417.                 GOTO UNDO
  20418.             END
  20419.         END
  20420.         
  20421.         -- If article level reinit, reinit dependent articles in the publication as well    
  20422.         if @article <> '%'
  20423.         begin
  20424.             -- Reinit articles on which the current article depends on.
  20425.             declare @objid int, @pubid int, @srvid smallint,
  20426.                 @pre_creation_cmd tinyint
  20427.             select @pubid = pubid from syspublications where name = @pub
  20428.             select @objid = objid,
  20429.                     @pre_creation_cmd = pre_creation_cmd from sysarticles where 
  20430.                 pubid = @pubid and 
  20431.                 name = @art_name
  20432.             -- @sub_name is from sysservers, no need to upper it.
  20433.             select @srvid = srvid from master..sysservers where srvname = @sub_name collate database_default
  20434.             -- set virtual id if needed
  20435.             if @srvid is null
  20436.                 select @srvid = -1
  20437.  
  20438.             -- Have to use temp cursor name otherwise we will get a 'cursor already exists' error
  20439.             -- in recursive calls.
  20440.             DECLARE #hCdep CURSOR LOCAL FAST_FORWARD FOR
  20441.                 SELECT distinct art.name from sysextendedarticlesview art, syssubscriptions s where
  20442.                     art.pubid = @pubid and
  20443.                     s.artid = art.artid and
  20444.                     s.srvid = @srvid and
  20445.                     s.dest_db = @dest_db and
  20446.                     s.status = @active and
  20447.                     -- Has dri on referencing table or not
  20448.                     (convert(int, substring(art.schema_option, len(art.schema_option) - 2 + 1, 2)) & 0x00000200 <> 0 and
  20449.                       -- If the article schema option includes DRI, reinit articles that have 
  20450.                       -- forein key relationship on this table, have to do this
  20451.                       -- otherwise dist will fail because we cannot drop or delete base table.
  20452.                       exists ( select * from  sysreferences r where
  20453.                             r.rkeyid = @objid and
  20454.                             art.objid = r.fkeyid) or
  20455.                       -- If there's a schema bound view on this table, reinit that view etc.
  20456.                       -- We have to do this for schema bound view other wise, we cannot drop the table
  20457.                      -- Only do it if precreation command is 'drop table'
  20458.                      (@pre_creation_cmd = 1 and
  20459.                       exists ( select * from sysdepends d where
  20460.                             d.depid = @objid and
  20461.                             art.objid = d.id and
  20462.                             objectproperty(art.objid, 'IsSchemaBound') = 1)))
  20463.             FOR READ ONLY
  20464.  
  20465.             OPEN #hCdep
  20466.  
  20467.             -- Note: @art_name is changed
  20468.             FETCH #hCdep INTO @art_name
  20469.  
  20470.             WHILE (@@fetch_status <> -1)
  20471.             BEGIN
  20472.                 EXEC @retcode = dbo.sp_reinitsubscription
  20473.                     @publication = @pub,
  20474.                     @article = @art_name,
  20475.                     @subscriber = @sub_name,
  20476.                     @destination_db = @dest_db,
  20477.                     @for_schema_change = @for_schema_change
  20478.                 IF @@ERROR <> 0 OR @retcode <> 0
  20479.                     GOTO UNDO
  20480.                 FETCH #hCdep INTO @art_name
  20481.             END
  20482.             
  20483.             CLOSE #hCdep
  20484.             DEALLOCATE #hCdep
  20485.         end
  20486.     
  20487.         COMMIT TRAN 
  20488.  
  20489.         FETCH hCresyncsub INTO @pub, @immediate_sync, @art_name, @sub_name, 
  20490.             @dest_db, @sync_type, @subscription_type, @login_name
  20491.     END
  20492.  
  20493.     CLOSE hCresyncsub
  20494.     DEALLOCATE hCresyncsub
  20495.  
  20496.     RETURN(0)
  20497.  
  20498. UNDO:
  20499.     IF @@TRANCOUNT > 0
  20500.     begin
  20501.         ROLLBACK TRAN sp_reinitsubscription
  20502.         COMMIT TRAN
  20503.     end
  20504.     return 1
  20505. go
  20506.  
  20507. EXEC dbo.sp_MS_marksystemobject sp_reinitsubscription
  20508. GO
  20509.  
  20510. dump tran master with no_log
  20511. GO
  20512.  
  20513.  
  20514.  
  20515. --------------------------------------------------------------------
  20516. --------------------------------------------------------------------
  20517.  
  20518. print ''
  20519. print 'Creating procedure sp_MSareallcolumnscomputed'
  20520. go
  20521. create procedure sp_MSareallcolumnscomputed @tabid int, @colbitmap binary(32)
  20522. as
  20523. declare @isset int
  20524. declare @retcode int
  20525. declare @this_col int
  20526.  
  20527. select @retcode = 1
  20528.  
  20529. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  20530. select colid from syscolumns where id = @tabid order by colid asc
  20531.  
  20532. OPEN hCColid
  20533.  
  20534. FETCH hCColid INTO @this_col
  20535.  
  20536. WHILE (@@fetch_status <> -1)
  20537. BEGIN
  20538.     exec @isset = dbo.sp_isarticlecolbitset @this_col, @colbitmap
  20539.     if @isset != 0 and EXISTS (select name from syscolumns where id=@tabid and @this_col=colid and iscomputed<>1)
  20540.     BEGIN 
  20541.         select @retcode = 0
  20542.         break
  20543.     END
  20544.     FETCH hCColid INTO @this_col
  20545. END
  20546. CLOSE hCColid
  20547. DEALLOCATE hCColid
  20548.  
  20549. return @retcode
  20550. GO
  20551.  
  20552. EXEC dbo.sp_MS_marksystemobject sp_MSareallcolumnscomputed
  20553. GO
  20554. -----------------------------------------------------------
  20555. -----------------------------------------------------------
  20556.  
  20557. print ''
  20558. print 'Creating procedure sp_MSgettypestringudt'
  20559. go
  20560.  
  20561. create procedure sp_MSgettypestringudt @tabid int, @colid int, @typestring nvarchar(255) output
  20562. as
  20563. declare @coltypename sysname
  20564. declare @coltype  tinyint
  20565. declare @colusertype smallint
  20566. declare @collen   smallint
  20567. declare @colprec  tinyint
  20568. declare @colscale tinyint
  20569.  
  20570. select @coltypename = type_name( sc.xusertype ), @colusertype = sc.xusertype, @coltype = sc.xtype,
  20571.        @collen = sc.length, @colprec = sc.xprec, @colscale = sc.xscale
  20572. from syscolumns sc 
  20573. where sc.id = @tabid
  20574. and sc.colid = @colid
  20575. --and st.xtype = sc.xtype
  20576. --and st.xtype = st.xusertype
  20577.  
  20578. select @typestring = @coltypename
  20579.  
  20580. -- if it's not a user defined type, script out length/prec/scale as necessary
  20581. if @colusertype = @coltype 
  20582. begin
  20583.     if @coltypename in (N'char', N'varchar', N'binary', N'varbinary')
  20584.     begin
  20585.         select @typestring = @typestring + N'(' + convert(nvarchar,@collen) + N')'
  20586.     end
  20587.     else if @coltypename in (N'nchar', N'nvarchar' )
  20588.     begin
  20589.         select @typestring = @typestring + N'(' + convert(nvarchar,@collen/2) + N')'
  20590.     end
  20591.     else if @coltype = 108 or @coltype = 106
  20592.     begin
  20593.         select @typestring = @typestring + N'(' + convert(nvarchar,@colprec) + N',' + convert(nvarchar,@colscale) + N')'
  20594.     end
  20595.     else if @coltype = 189
  20596.     begin
  20597.         select @typestring = N'binary(8)'
  20598.     end
  20599. end
  20600.     
  20601. go
  20602.  
  20603. EXEC dbo.sp_MS_marksystemobject sp_MSgettypestringudt
  20604. GO
  20605.  
  20606. --------------------------------------------------------------------
  20607. --------------------------------------------------------------------
  20608.  
  20609. print ''
  20610. print 'Creating procedure sp_gettypestring'
  20611. go
  20612.  
  20613. create procedure sp_gettypestring @tabid int, @colid int, @typestring nvarchar(255) output
  20614. as
  20615. declare @coltypename sysname
  20616. declare @coltype  tinyint
  20617. declare @colvar   bit
  20618. declare @collen   smallint
  20619. declare @colprec  tinyint
  20620. declare @colscale tinyint
  20621.  
  20622. select @coltypename = st.name, @coltype = st.xtype, @colvar = st.variable, 
  20623.        @collen = sc.length, @colprec = sc.xprec, @colscale = sc.xscale
  20624. from systypes st, syscolumns sc 
  20625. where sc.id = @tabid
  20626. and sc.colid = @colid
  20627. and st.xtype = sc.xtype
  20628. and st.xtype = st.xusertype
  20629.  
  20630. select @typestring = @coltypename
  20631.  
  20632. if @coltypename in (N'char', N'varchar', N'binary', N'varbinary')
  20633. begin
  20634.     select @typestring = @typestring + N'(' + convert(nvarchar,@collen) + N')'
  20635. end
  20636. else if @coltypename in (N'nchar', N'nvarchar' )
  20637. begin
  20638.     select @typestring = @typestring + N'(' + convert(nvarchar,@collen/2) + N')'
  20639. end
  20640. else if @coltype = 108 or @coltype = 106
  20641. begin
  20642.     select @typestring = @typestring + N'(' + convert(nvarchar,@colprec) + N',' + convert(nvarchar,@colscale) + N')'
  20643. end
  20644. else if @coltype = 189
  20645. begin
  20646.     select @typestring = N'binary(8)'
  20647. end
  20648.     
  20649. go
  20650.  
  20651. EXEC dbo.sp_MS_marksystemobject sp_gettypestring
  20652. GO
  20653.  
  20654. --------------------------------------------------------------------
  20655. --------------------------------------------------------------------
  20656.  
  20657.  
  20658.  
  20659. --------------------------------------------------------------------
  20660. --------------------------------------------------------------------
  20661.  
  20662. print ''
  20663. print 'sp_scriptpkwhereclause'
  20664. go
  20665.  
  20666. create procedure sp_scriptpkwhereclause @src_objid int, @pkcolumns binary(32),
  20667. @prefix nvarchar(10) = N'@pkc',
  20668. @artcolumns binary(32) = NULL
  20669. as
  20670. declare @this_col int
  20671. declare @art_col int
  20672. declare @spacer nvarchar(10)
  20673. declare @isset int
  20674. declare @cmd nvarchar(4000)
  20675.  
  20676. -- create WHERE clause
  20677.  
  20678. select @art_col = 0
  20679. select @spacer = N' '
  20680. select @cmd = N'where'
  20681.  
  20682. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  20683. select colid from syscolumns where id = @src_objid order by colid asc
  20684.  
  20685. OPEN hCColid
  20686.  
  20687. FETCH hCColid INTO @this_col
  20688.  
  20689. WHILE (@@fetch_status <> -1)
  20690. begin
  20691.     if EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid)
  20692.     begin
  20693.         -- If @artcolumns is not null, it is called from 
  20694.         -- sp_scriptxupdproc or sp_scriptxdelproc
  20695.         -- Use counter in article column bitmap
  20696.         -- Otherwise use counter in pk bitmap
  20697.         if @artcolumns is not null
  20698.         begin
  20699.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  20700.             if @isset != 0
  20701.                 select @art_col = @art_col + 1
  20702.         end
  20703.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  20704.         if @isset != 0 
  20705.         begin
  20706.             if @artcolumns is null
  20707.                 select @art_col = @art_col + 1
  20708.             select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = ' + @prefix + convert( nvarchar, @art_col ) 
  20709.             select @spacer = N' and '
  20710.             if len( @cmd ) > 3000
  20711.             begin
  20712.                 insert into #proctext(procedure_text) values( @cmd )
  20713.                 select @cmd = N''
  20714.             end
  20715.         end
  20716.     end
  20717.     FETCH hCColid INTO @this_col
  20718. end
  20719. CLOSE hCColid
  20720. DEALLOCATE hCColid
  20721.  
  20722. insert into #proctext(procedure_text) values( @cmd )
  20723.  
  20724. go
  20725.  
  20726. EXEC dbo.sp_MS_marksystemobject sp_scriptpkwhereclause
  20727. GO
  20728.  
  20729. --------------------------------------------------------------------
  20730. --------------------------------------------------------------------
  20731.  
  20732. print ''
  20733. print 'sp_MSscript_missing_row_check'
  20734. go
  20735.  
  20736. create procedure sp_MSscript_missing_row_check 
  20737. as
  20738.  
  20739. -- Note this must be done immediately after the update or delete statement.
  20740. -- create WHERE clause
  20741.  
  20742. insert into #proctext(procedure_text) values( N'if @@rowcount = 0' )
  20743. begin
  20744.     insert into #proctext(procedure_text) values( N'    if @@microsoftversion>0x07320000' )
  20745.     insert into #proctext(procedure_text) values( N'        exec sp_MSreplraiserror 20598' )
  20746. end
  20747. go
  20748.  
  20749. EXEC dbo.sp_MS_marksystemobject sp_MSscript_missing_row_check
  20750. GO
  20751.  
  20752. --------------------------------------------------------------------
  20753. --------------------------------------------------------------------
  20754.  
  20755. print ''
  20756. print 'Create procedure sp_scriptupdateparams'
  20757. go
  20758.  
  20759. create procedure sp_scriptupdateparams @src_objid int, @artcolumns binary(32), 
  20760. @pkcolumns binary(32), -- If it is null we are called by sp_scriptxupdproc
  20761. @param_count int = NULL output
  20762. as
  20763. declare @this_col int
  20764. declare @art_col int
  20765. declare @spacer nvarchar(10)
  20766. declare @isset int
  20767. declare @cmd nvarchar(4000)
  20768. declare @typestring nvarchar(255)
  20769.  
  20770. -- add colval parameters
  20771. select @param_count = NULL
  20772. select @art_col = 1
  20773. select @spacer = N' '
  20774. select @cmd = ''
  20775.  
  20776. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  20777. select colid from syscolumns where id = @src_objid order by colid asc
  20778.  
  20779. OPEN hCColid
  20780.  
  20781. FETCH hCColid INTO @this_col
  20782.  
  20783. WHILE ( 1 = 1 )
  20784. begin
  20785.     if @@fetch_status = -1
  20786.     begin
  20787.         -- If called by sp_scriptxupdproc and it is the first time
  20788.         -- at the end of the cursor loop
  20789.         if @pkcolumns is null and @param_count is NULL
  20790.         begin
  20791.             -- Reset it so that we know we encountered cursor end once.
  20792.             select @param_count = 0
  20793.             -- Reopen cursor
  20794.             CLOSE hCColid
  20795.             OPEN hCColid
  20796.             FETCH hCColid INTO @this_col
  20797.             continue
  20798.         end
  20799.         else
  20800.             break;
  20801.     end
  20802.     exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  20803.     if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  20804.     begin
  20805.         exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  20806.         select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  20807.         select @art_col = @art_col + 1
  20808.         select @spacer = N','
  20809.  
  20810.         if len( @cmd ) > 3000
  20811.         begin
  20812.         insert into #proctext(procedure_text) values( @cmd )
  20813.             select @cmd = N''
  20814.         end
  20815.     end
  20816.     FETCH hCColid INTO @this_col
  20817. end
  20818. CLOSE hCColid
  20819. DEALLOCATE hCColid
  20820.  
  20821. select @param_count = @art_col -1
  20822.  
  20823. -- add pkval parameters
  20824. -- If it is null we are called by sp_scriptxupdproc, no need for PK params
  20825. if @pkcolumns is not null
  20826. begin
  20827.     select @art_col = 1
  20828.  
  20829.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  20830.     select colid from syscolumns where id = @src_objid order by colid asc
  20831.  
  20832.     OPEN hCColid
  20833.  
  20834.     FETCH hCColid INTO @this_col
  20835.  
  20836.     WHILE (@@fetch_status <> -1)
  20837.     begin
  20838.        exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  20839.        if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid )
  20840.        begin
  20841.             exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  20842.             select @cmd = @cmd + @spacer + N'@pkc' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  20843.             select @art_col = @art_col + 1
  20844.             select @spacer = N','
  20845.  
  20846.             if len( @cmd ) > 3000
  20847.             begin
  20848.             insert into #proctext(procedure_text) values( @cmd )
  20849.                 select @cmd = N''
  20850.             end
  20851.         end
  20852.         FETCH hCColid INTO @this_col
  20853.     end
  20854.     CLOSE hCColid
  20855.     DEALLOCATE hCColid
  20856. end
  20857.  
  20858. insert into #proctext(procedure_text) values ( @cmd )
  20859.  
  20860. go
  20861.  
  20862. EXEC dbo.sp_MS_marksystemobject sp_scriptupdateparams
  20863. GO
  20864.  
  20865.  
  20866. print ''
  20867. print 'Creating procedure sp_scriptreconwhereclause'
  20868. go
  20869.  
  20870. create procedure sp_scriptreconwhereclause @src_objid int, @pkcolumns binary(32), @artcolumns binary(32)
  20871. as
  20872. declare @this_col int
  20873. declare @art_col int
  20874. declare @spacer nvarchar(10)
  20875. declare @isset int
  20876. declare @cmd nvarchar(4000)
  20877.  
  20878. -- create WHERE clause
  20879.  
  20880. select @art_col = 1
  20881. select @spacer = N' '
  20882. select @cmd = N'where'
  20883.  
  20884. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  20885. select colid from syscolumns where id = @src_objid order by colid asc
  20886.  
  20887. OPEN hCColid
  20888.  
  20889. FETCH hCColid INTO @this_col
  20890.  
  20891. WHILE (@@fetch_status <> -1)
  20892. begin
  20893.     exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  20894.     if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid )
  20895.     begin
  20896.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  20897.         if @isset != 0 
  20898.         begin
  20899.             select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = @c' + convert( nvarchar, @art_col ) 
  20900.             select @spacer = N' and '
  20901.  
  20902.             if len( @cmd ) > 3000
  20903.             begin
  20904.                 insert into #proctext(procedure_text) values( @cmd )
  20905.                 select @cmd = N''
  20906.             end
  20907.         end
  20908.         select @art_col = @art_col + 1
  20909.     end
  20910.     FETCH hCColid INTO @this_col
  20911. end
  20912. CLOSE hCColid
  20913. DEALLOCATE hCColid
  20914.  
  20915. insert into #proctext(procedure_text) values( @cmd )
  20916.  
  20917. go
  20918.  
  20919. EXEC dbo.sp_MS_marksystemobject sp_scriptreconwhereclause
  20920. GO
  20921.  
  20922.  
  20923.  
  20924.  
  20925. --------------------------------------------------------------------
  20926. --------------------------------------------------------------------
  20927.  
  20928. print ''
  20929. print 'Creating procedure sp_script_reconciliation_insproc'
  20930. go
  20931.  
  20932. create procedure sp_script_reconciliation_insproc (
  20933.     @artid int)
  20934. as
  20935. BEGIN
  20936. declare @cmd          nvarchar(4000)
  20937. declare @dest_owner   nvarchar(255)
  20938. declare @dest_tabname sysname
  20939. declare @src_objid    int
  20940. declare @artcolumns   binary(32)
  20941. declare @pkcolumns    binary(32)
  20942. declare @ins_cmd      nvarchar(255)
  20943. declare @dest_proc    sysname
  20944. declare @this_col     int
  20945. declare @art_col      int
  20946. declare @isset        int
  20947.  
  20948. declare @typestring   nvarchar(255)
  20949. declare @spacer       nvarchar(1)
  20950.     , @identity_insert bit
  20951.     
  20952.  
  20953. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  20954. begin
  20955.     raiserror (14155, 16, 1 )
  20956.     return 1
  20957. end
  20958.  
  20959. -------- create temp table for command fragments
  20960.  
  20961. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  20962.  
  20963. -------- get sysarticles information
  20964.  
  20965. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  20966.        @src_objid = objid, @artcolumns = columns, @ins_cmd = ins_cmd
  20967. from sysarticles
  20968. where artid = @artid
  20969.  
  20970. if @dest_owner is not null
  20971. begin
  20972.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  20973. end
  20974. else
  20975. begin
  20976.     select @dest_owner = N''
  20977. end
  20978.  
  20979. -- Check to see if identity insert must be turned on
  20980. -- i.e. Does the table has identity that are included in the partition?
  20981. exec sp_MSis_identity_insert null, null, @identity_insert output, @artid
  20982. --
  20983.  
  20984. -------- get dest proc name
  20985.  
  20986. if( 1 != charindex( N'CALL', upper(@ins_cmd) ) ) or @ins_cmd is null
  20987. begin
  20988.     raiserror (14156, 16, 1 )
  20989.     return 1
  20990. end
  20991.  
  20992. select @dest_proc = substring( @ins_cmd, 6, len( @ins_cmd ) - 4 )
  20993. select @cmd = N'create procedure ' + QUOTENAME(@dest_proc) + N';2'
  20994.  
  20995. -------- construct parameter list
  20996.  
  20997.  
  20998. select @art_col = 1
  20999. select @spacer = N' '
  21000.  
  21001. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  21002. select colid from syscolumns where id = @src_objid order by colid asc
  21003.  
  21004. OPEN hCColid
  21005.  
  21006. FETCH hCColid INTO @this_col
  21007.  
  21008. WHILE (@@fetch_status <> -1)
  21009. begin
  21010.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  21011.    if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  21012.    begin
  21013.         if len( @cmd ) > 3000
  21014.         begin
  21015.         insert into #proctext(procedure_text) values( @cmd )
  21016.             select @cmd = N''
  21017.         end
  21018.  
  21019.         exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  21020.         select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  21021.         select @art_col = @art_col + 1
  21022.         select @spacer = N','
  21023.    end
  21024.    FETCH hCColid INTO @this_col
  21025. end
  21026. CLOSE hCColid
  21027. DEALLOCATE hCColid
  21028.  
  21029.  
  21030. -- save off cmd fragment
  21031.  
  21032. insert into #proctext(procedure_text) values( @cmd )
  21033.  
  21034. insert into #proctext(procedure_text) values( N'as' )
  21035.  
  21036. ------- construct proc body
  21037.  
  21038. ---- if already exists, apply as update
  21039.  
  21040. insert into #proctext(procedure_text) 
  21041.     values( N'if exists ( select * from ' + @dest_owner + QUOTENAME(@dest_tabname) )
  21042. exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  21043. exec dbo.sp_scriptreconwhereclause @src_objid, @pkcolumns, @artcolumns
  21044. insert into #proctext(procedure_text) values( N')' )
  21045. insert into #proctext(procedure_text) values (N'begin')
  21046.  
  21047.  
  21048. if( @artcolumns != @pkcolumns )
  21049. begin
  21050.     -- construct update 
  21051.  
  21052.     select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set'
  21053.  
  21054.     -- create SET clause
  21055.  
  21056.     select @art_col = 1
  21057.     select @spacer = N' '
  21058.  
  21059.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  21060.     select colid from syscolumns where id = @src_objid order by colid asc
  21061.  
  21062.     OPEN hCColid
  21063.  
  21064.     FETCH hCColid INTO @this_col
  21065.  
  21066.     WHILE (@@fetch_status <> -1)
  21067.     begin
  21068.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  21069.         if @isset != 0  and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  21070.         begin
  21071.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  21072.             if @isset = 0
  21073.             begin
  21074.                 if not (@identity_insert = 1 and 
  21075.                     columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  21076.                 begin
  21077.                     select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = @c' + convert( nvarchar, @art_col ) 
  21078.                     select @spacer = N','
  21079.  
  21080.                     if len( @cmd ) > 3000
  21081.                     begin
  21082.                         insert into #proctext(procedure_text) values( @cmd )
  21083.                         select @cmd = N''
  21084.                     end
  21085.                 end
  21086.             end
  21087.             select @art_col = @art_col + 1
  21088.         end
  21089.         FETCH hCColid INTO @this_col
  21090.        end
  21091.     CLOSE hCColid
  21092.     DEALLOCATE hCColid
  21093.  
  21094.     insert into #proctext(procedure_text) values( @cmd )
  21095.  
  21096.     exec dbo.sp_scriptreconwhereclause @src_objid, @pkcolumns, @artcolumns
  21097. end
  21098.  
  21099. -- all article columns are included in the PK, & PK already exists, do nothing
  21100. else 
  21101. begin
  21102.     insert into #proctext(procedure_text ) values( N'return' )
  21103. end
  21104.  
  21105.  
  21106. insert into #proctext(procedure_text) values (N'end')
  21107. insert into #proctext(procedure_text) values (N'else')
  21108. insert into #proctext(procedure_text) values (N'begin')
  21109.  
  21110. ---- normal insert
  21111.  
  21112. -- set identity_insert on
  21113. if @identity_insert = 1
  21114. begin
  21115.     select @cmd = N'
  21116. set identity_insert ' + @dest_owner + QUOTENAME(@dest_tabname) + ' on'
  21117.     insert into #proctext(procedure_text) values( @cmd )
  21118. end
  21119.  
  21120. -- prepare the column list
  21121.  
  21122. select @cmd = N'insert into ' + @dest_owner + QUOTENAME(@dest_tabname) + N' ('
  21123. select @art_col = 1
  21124. select @spacer = N' '
  21125.  
  21126. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  21127. select colid from syscolumns where id = @src_objid order by colid asc
  21128.  
  21129. OPEN hCColid
  21130.  
  21131. FETCH hCColid INTO @this_col
  21132.  
  21133. WHILE (@@fetch_status <> -1)
  21134. begin
  21135.     exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  21136.     if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  21137.     begin
  21138.         if len( @cmd ) > 3000
  21139.         begin
  21140.         insert into #proctext(procedure_text) values( @cmd )
  21141.             select @cmd = N''
  21142.         end
  21143.  
  21144.         select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col))  
  21145.         select @art_col = @art_col + 1
  21146.         select @spacer = N','
  21147.     end
  21148.     FETCH hCColid INTO @this_col
  21149. end
  21150. CLOSE hCColid
  21151. DEALLOCATE hCColid
  21152.  
  21153. -- now the data parameter list
  21154.  
  21155. select @cmd = @cmd + N' ) values ('
  21156. select @art_col = 1
  21157. select @spacer = N' '
  21158.  
  21159. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  21160. select colid from syscolumns where id = @src_objid order by colid asc
  21161.  
  21162. OPEN hCColid
  21163.  
  21164. FETCH hCColid INTO @this_col
  21165.  
  21166. WHILE (@@fetch_status <> -1)
  21167. begin
  21168.     exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  21169.     if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  21170.     begin
  21171.         if len( @cmd ) > 3000
  21172.         begin
  21173.         insert into #proctext(procedure_text) values( @cmd )
  21174.             select @cmd = N''
  21175.         end
  21176.  
  21177.         select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) 
  21178.         select @art_col = @art_col + 1
  21179.         select @spacer = N','
  21180.     end
  21181.     FETCH hCColid INTO @this_col
  21182. end
  21183. CLOSE hCColid
  21184. DEALLOCATE hCColid
  21185.  
  21186. -- finish up proc body
  21187.  
  21188. select @cmd = @cmd + N' )'
  21189.  
  21190. -- save off cmd fragement
  21191.  
  21192. insert into #proctext(procedure_text) values( @cmd )
  21193.  
  21194. -- set identity_insert off
  21195. if @identity_insert = 1
  21196. begin
  21197.     select @cmd = N'
  21198. set identity_insert ' + @dest_owner + QUOTENAME(@dest_tabname) + ' off'
  21199.     insert into #proctext(procedure_text) values( @cmd )
  21200. end
  21201.  
  21202. insert into #proctext(procedure_text) values (N'end')
  21203.  
  21204. -- send fragments to client
  21205.  
  21206. select procedure_text from #proctext order by c1 asc
  21207. END
  21208. go
  21209.  
  21210. EXEC dbo.sp_MS_marksystemobject sp_script_reconciliation_insproc
  21211. GO
  21212.  
  21213.  
  21214. --------------------------------------------------------------------
  21215. --------------------------------------------------------------------
  21216.  
  21217. print ''
  21218. print 'Creating procedure sp_script_reconciliation_delproc'
  21219. go
  21220.  
  21221. create procedure sp_script_reconciliation_delproc @artid int
  21222. as
  21223. declare @cmd          nvarchar(4000)
  21224. declare @dest_owner   nvarchar(255)
  21225. declare @dest_tabname sysname
  21226. declare @src_objid    int
  21227. declare @pkcolumns    binary(32)
  21228. declare @del_cmd      nvarchar(255)
  21229. declare @dest_proc    sysname
  21230. declare @this_col     int
  21231. declare @art_col      int
  21232. declare @isset        int
  21233.  
  21234. declare @typestring   nvarchar(255)
  21235. declare @spacer       nvarchar(10)
  21236.  
  21237. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  21238. begin
  21239.     raiserror (14155, 16, 1 )
  21240.     return 1
  21241. end
  21242.  
  21243. -------- create temp table for command fragments
  21244.  
  21245. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  21246.  
  21247. -- get sysarticles information
  21248.  
  21249. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  21250.        @src_objid = objid, @del_cmd = del_cmd
  21251. from sysarticles
  21252. where artid = @artid
  21253.  
  21254. if @dest_owner is not null
  21255. begin
  21256.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  21257. end
  21258. else
  21259. begin
  21260.     select @dest_owner = N''
  21261. end
  21262.  
  21263. -------- get dest proc name
  21264.  
  21265. if( 1 != charindex( N'CALL', upper(@del_cmd) ) ) or @del_cmd is null
  21266. begin
  21267.     raiserror (14156, 16, 1 )
  21268.     return 1
  21269. end
  21270.  
  21271. select @dest_proc = substring( @del_cmd, 6, len( @del_cmd ) - 4 )
  21272. select @cmd = N'create procedure ' + QUOTENAME(@dest_proc) + N';2'
  21273.  
  21274.  
  21275. -------- construct parameter list
  21276.  
  21277.  
  21278. select @art_col = 1
  21279. select @spacer = N' '
  21280.  
  21281. exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  21282.  
  21283. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  21284. select colid from syscolumns where id = @src_objid order by colid asc
  21285.  
  21286. OPEN hCColid
  21287.  
  21288. FETCH hCColid INTO @this_col
  21289.  
  21290. WHILE (@@fetch_status <> -1)
  21291. begin
  21292.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  21293.    if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid )
  21294.    begin
  21295.         if len( @cmd ) > 3000
  21296.         begin
  21297.         insert into #proctext(procedure_text) values( @cmd )
  21298.             select @cmd = N''
  21299.         end
  21300.  
  21301.         exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  21302.         select @cmd = @cmd + @spacer + N'@pkc' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  21303.         select @art_col = @art_col + 1
  21304.         select @spacer = N','
  21305.    end
  21306.     FETCH hCColid INTO @this_col
  21307. end
  21308.  
  21309. CLOSE hCColid
  21310. DEALLOCATE hCColid
  21311.  
  21312. -- save off 
  21313.  
  21314. insert into #proctext(procedure_text) values( @cmd )
  21315. insert into #proctext(procedure_text) values( N'as' )
  21316.  
  21317. ------- construct proc body
  21318.  
  21319. insert into #proctext(procedure_text) values( N'delete ' + @dest_owner + QUOTENAME(@dest_tabname) ) 
  21320.  
  21321. exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns
  21322.  
  21323. -- flush to client
  21324.  
  21325. select procedure_text from #proctext order by c1 asc
  21326.  
  21327.  
  21328. go
  21329.  
  21330. EXEC dbo.sp_MS_marksystemobject sp_script_reconciliation_delproc
  21331. GO
  21332.  
  21333. --------------------------------------------------------------------
  21334. --------------------------------------------------------------------
  21335.  
  21336. print ''
  21337. print 'Creating procedure sp_script_reconciliation_xdelproc'
  21338. go
  21339.  
  21340. create procedure sp_script_reconciliation_xdelproc @artid int
  21341. as
  21342. declare @cmd          nvarchar(4000)
  21343. declare @dest_owner   nvarchar(255)
  21344. declare @dest_tabname sysname
  21345. declare @src_objid    int
  21346. declare @columns    binary(32)
  21347. declare @pkcolumns    binary(32)
  21348. declare @del_cmd      nvarchar(255)
  21349. declare @dest_proc    sysname
  21350. declare @this_col     int
  21351. declare @art_col      int
  21352. declare @isset        int
  21353.  
  21354. declare @typestring   nvarchar(255)
  21355. declare @spacer       nvarchar(10)
  21356.  
  21357. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  21358. begin
  21359.     raiserror (14155, 16, 1 )
  21360.     return 1
  21361. end
  21362.  
  21363. -------- create temp table for command fragments
  21364.  
  21365. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  21366.  
  21367. -- get sysarticles information
  21368.  
  21369. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  21370.        @src_objid = objid, @del_cmd = del_cmd, @columns = columns
  21371. from sysarticles
  21372. where artid = @artid
  21373.  
  21374. if @dest_owner is not null
  21375. begin
  21376.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  21377. end
  21378. else
  21379. begin
  21380.     select @dest_owner = N''
  21381. end
  21382.  
  21383. -------- get dest proc name
  21384.  
  21385. if( 1 != charindex( N'XCALL', upper(@del_cmd) ) ) or @del_cmd is null
  21386. begin
  21387.     raiserror (14156, 16, 1 )
  21388.     return 1
  21389. end
  21390.  
  21391. select @dest_proc = substring( @del_cmd, 7, len( @del_cmd ) - 5 )
  21392. select @cmd = N'create procedure ' + QUOTENAME(@dest_proc) + N';2'
  21393.  
  21394. -------- construct parameter list
  21395.  
  21396.  
  21397. select @art_col = 1
  21398. select @spacer = N' '
  21399.  
  21400. exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  21401.  
  21402. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  21403. select colid from syscolumns where id = @src_objid order by colid asc
  21404.  
  21405. OPEN hCColid
  21406.  
  21407. FETCH hCColid INTO @this_col
  21408.  
  21409. WHILE (@@fetch_status <> -1)
  21410. begin
  21411.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  21412.    if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  21413.    begin
  21414.         if len( @cmd ) > 3000
  21415.         begin
  21416.         insert into #proctext(procedure_text) values( @cmd )
  21417.             select @cmd = N''
  21418.         end
  21419.  
  21420.         exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  21421.         select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  21422.         select @art_col = @art_col + 1
  21423.         select @spacer = N','
  21424.    end
  21425.    FETCH hCColid INTO @this_col
  21426. end
  21427.  
  21428. CLOSE hCColid
  21429. DEALLOCATE hCColid
  21430.  
  21431. -- save off 
  21432.  
  21433. insert into #proctext(procedure_text) values( @cmd )
  21434. insert into #proctext(procedure_text) values( N'as' )
  21435.  
  21436. ------- construct proc body
  21437.  
  21438. insert into #proctext(procedure_text) values( N'delete ' + @dest_owner + QUOTENAME(@dest_tabname) ) 
  21439.  
  21440. exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns, N'@c', @columns
  21441.  
  21442. -- flush to client
  21443.  
  21444. select procedure_text from #proctext order by c1 asc
  21445.  
  21446.  
  21447.  
  21448.  
  21449. go
  21450.  
  21451. EXEC dbo.sp_MS_marksystemobject sp_script_reconciliation_xdelproc
  21452. GO
  21453.  
  21454.  
  21455. --------------------------------------------------------------------
  21456. --------------------------------------------------------------------
  21457.  
  21458. print ''
  21459. print 'Creating procedure sp_scriptinsproc'
  21460. go
  21461.  
  21462. create procedure sp_scriptinsproc (
  21463.     @artid int)
  21464. as
  21465. BEGIN
  21466. declare @cmd          nvarchar(4000)
  21467.         ,@dest_owner   nvarchar(255)
  21468.         ,@dest_tabname sysname
  21469.         ,@src_objid    int
  21470.         ,@columns      binary(32)
  21471.         ,@ins_cmd      nvarchar(255)
  21472.         ,@dest_proc    sysname
  21473.         ,@this_col     int
  21474.         ,@art_col      int
  21475.         ,@isset        int
  21476.         ,@pubid          int
  21477.  
  21478.         ,@identity_insert bit
  21479.         ,@rc int
  21480.         ,@colname sysname
  21481.         ,@ccoltype     sysname
  21482.         ,@typestring   nvarchar(255)
  21483.         ,@spacer       nvarchar(1)
  21484.         ,@queued_check bit
  21485.         ,@column_string nvarchar(4000)
  21486.         ,@var_string nvarchar(4000)
  21487.         ,@qwhere_string nvarchar(4000)
  21488.         ,@indkey      int
  21489.         ,@indid       int
  21490.  
  21491. set nocount on
  21492.  
  21493. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  21494. begin
  21495.     raiserror (14155, 16, 1 )
  21496.     return 1
  21497. end
  21498.  
  21499. -------- create temp table for command fragments and insert column list
  21500.  
  21501. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  21502. create table #collisttab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  21503.  
  21504. -------- get sysarticles information
  21505.  
  21506. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  21507.        @src_objid = objid, @columns = columns, @ins_cmd = ins_cmd,
  21508.        @pubid = pubid
  21509. from sysarticles
  21510. where artid = @artid
  21511.  
  21512. -- Check to see if identity insert must be turned on
  21513. -- i.e. Does the table has identity that are included in the partition?
  21514. exec sp_MSis_identity_insert null, null, @identity_insert output, @artid
  21515. --
  21516.  
  21517. if @dest_owner is not null
  21518. begin
  21519.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  21520. end
  21521. else
  21522. begin
  21523.     select @dest_owner = N''
  21524. end
  21525.  
  21526. -- Check if this is a queued publication
  21527. select @queued_check = ISNULL(allow_queued_tran, 0) 
  21528. from syspublications
  21529. where pubid = @pubid
  21530.  
  21531. -------- get dest proc name
  21532.  
  21533. if( 1 != charindex( N'CALL', upper(@ins_cmd) ) ) or @ins_cmd is null
  21534. begin
  21535.     raiserror (14156, 16, 1 )
  21536.     return 1
  21537. end
  21538.  
  21539. select @dest_proc = substring( @ins_cmd, 6, len( @ins_cmd ) - 4 )
  21540. select @cmd = N'if exists (select * from sysobjects where type = ''P'' and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  21541. insert into #proctext(procedure_text) values( @cmd )
  21542. insert into #proctext(procedure_text) values( N'go' )
  21543. select @cmd = N'create procedure ' + QUOTENAME(@dest_proc)
  21544.  
  21545. -------- construct parameter list
  21546.  
  21547.  
  21548. select @art_col = 1
  21549. select @spacer = N' '
  21550.  
  21551. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  21552. select colid from syscolumns where id = @src_objid order by colid asc
  21553.  
  21554. OPEN hCColid
  21555.  
  21556. FETCH hCColid INTO @this_col
  21557.  
  21558. WHILE (@@fetch_status <> -1)
  21559. begin
  21560.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  21561.    if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  21562.    begin
  21563.         if len( @cmd ) > 3000
  21564.         begin
  21565.         insert into #proctext(procedure_text) values( @cmd )
  21566.             select @cmd = N''
  21567.         end
  21568.  
  21569.         exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  21570.         select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  21571.         select @art_col = @art_col + 1
  21572.         select @spacer = N','
  21573.    end
  21574.    FETCH hCColid INTO @this_col
  21575. end
  21576.  
  21577. CLOSE hCColid
  21578. DEALLOCATE hCColid
  21579.  
  21580. -- save off cmd fragment
  21581.  
  21582. insert into #proctext(procedure_text) values( @cmd )
  21583.  
  21584. select @cmd = N'
  21585. AS
  21586. BEGIN
  21587. '
  21588. insert into #proctext(procedure_text) values( @cmd )
  21589.  
  21590. ------- construct proc body
  21591.  
  21592. -- For Queued case, build a temp table of index columns
  21593. -- we also need temp tables for where clause list
  21594. if (@queued_check = 1)
  21595. begin
  21596.     declare @source_object nvarchar(540)
  21597.  
  21598.     --
  21599.     -- Get the object owner name and build a owner qualified 
  21600.     -- source object name
  21601.     --
  21602.     select @source_object = QUOTENAME(u.name) 
  21603.     from sysusers u, sysobjects o 
  21604.     where o.id = @src_objid and o.uid = u.uid
  21605.  
  21606.     select @source_object = @source_object + N'.' + QUOTENAME(OBJECT_NAME(@src_objid))
  21607.  
  21608.     create table #wherecltab ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)    
  21609.     create table #indcoltab ( colname sysname collate database_default )
  21610.     
  21611.     exec @indid = dbo.sp_MStable_has_unique_index @src_objid
  21612.     select @indkey = 1;    
  21613.     while (@indkey <= 16)
  21614.     begin
  21615.         select @colname = index_col(@source_object, @indid, @indkey)
  21616.         if (@colname is NULL) 
  21617.             select @indkey = 16
  21618.         else
  21619.             insert into #indcoltab(colname) values(@colname)
  21620.  
  21621.         select @indkey = @indkey + 1
  21622.     end
  21623. end
  21624.  
  21625. -- Generate strings for col names and variables
  21626. select @art_col = 0
  21627. select @spacer = N' '
  21628.  
  21629. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  21630. select colid from syscolumns where id = @src_objid order by colid asc
  21631.  
  21632. OPEN hCColid
  21633.  
  21634. FETCH hCColid INTO @this_col
  21635.  
  21636. WHILE (@@fetch_status <> -1)
  21637. begin
  21638.     exec @rc = dbo.sp_MSget_colinfo @src_objid, @this_col, @columns, 1, @colname output, @ccoltype output
  21639.     if @rc = 0  and EXISTS (select name from syscolumns where id=@src_objid and colid=@this_col and iscomputed<>1)
  21640.     begin
  21641.         select @art_col = @art_col + 1
  21642.         if (@art_col = 1)
  21643.         begin
  21644.             select @column_string = QUOTENAME(@colname)
  21645.             select @var_string = N'@c' + cast(@art_col as nvarchar(4))
  21646.         end
  21647.         else
  21648.         begin
  21649.             select @column_string = @column_string + N', ' + QUOTENAME(@colname)
  21650.             select @var_string = @var_string + N', @c' + cast(@art_col as nvarchar(4))
  21651.         end
  21652.  
  21653.         -- transfer column list string to table if too large
  21654.         if (len(@column_string) > 3000)
  21655.         begin
  21656.             insert into #collisttab(procedure_text) values( @column_string )
  21657.             select @column_string = ' '
  21658.         end
  21659.  
  21660.         -- queued processing : add to where clause if column part of PK
  21661.         if (@queued_check = 1)
  21662.         begin
  21663.             if (@colname in (select colname from #indcoltab))
  21664.             begin
  21665.                 select @qwhere_string = case 
  21666.                     when (@qwhere_string IS NULL) then 
  21667.                         QUOTENAME(@colname) + N'=@c' + cast(@art_col as nvarchar(4))
  21668.                     else
  21669.                         @qwhere_string + N' and ' + QUOTENAME(@colname) + N'=@c' + cast(@art_col as nvarchar(4))
  21670.                     end
  21671.  
  21672.                 -- transfer where clause string to table if too large
  21673.                 if (len(@qwhere_string) > 3000)
  21674.                 begin
  21675.                     insert into #wherecltab(procedure_text) values( @qwhere_string )
  21676.                     select @qwhere_string = ' '
  21677.                 end
  21678.             end
  21679.         end
  21680.     end
  21681.     FETCH hCColid INTO @this_col
  21682. end
  21683.  
  21684. CLOSE hCColid
  21685. DEALLOCATE hCColid
  21686.  
  21687. -- insert the remaining strings for column list and where clause
  21688. insert into #collisttab(procedure_text) values( @column_string )
  21689. if (@queued_check = 1)
  21690.     insert into #wherecltab(procedure_text) values( @qwhere_string )
  21691.  
  21692. --
  21693. -- If we are a part of queued publication then 
  21694. -- insert only if PK does not exist
  21695. --
  21696. if (@queued_check = 1)
  21697. begin
  21698.     select @cmd = N'
  21699.     if not exists (select * from ' + @dest_owner + QUOTENAME(@dest_tabname) + N' 
  21700.         where '
  21701.     insert into #proctext(procedure_text) values( @cmd )
  21702.     insert into #proctext(procedure_text) 
  21703.         select procedure_text from #wherecltab order by c1 asc
  21704.     select @cmd = N')
  21705.     BEGIN'
  21706.     insert into #proctext(procedure_text) values( @cmd )
  21707.     drop table #wherecltab
  21708.     drop table #indcoltab
  21709. end
  21710.  
  21711.  
  21712. -- set identity_insert on
  21713. if @identity_insert = 1
  21714. begin
  21715.     select @cmd = N'
  21716.     set identity_insert ' + @dest_owner + QUOTENAME(@dest_tabname) + ' on'
  21717.     insert into #proctext(procedure_text) values( @cmd )
  21718. end
  21719.  
  21720.  
  21721. --
  21722. -- prepare the insert statement now
  21723. --
  21724. select @cmd = N'
  21725. insert into ' +  @dest_owner + QUOTENAME(@dest_tabname)  + N'( '
  21726. insert into #proctext(procedure_text) values( @cmd )
  21727. insert into #proctext(procedure_text) 
  21728.     select procedure_text from #collisttab order by c1 asc
  21729. select @cmd = N' )'
  21730. insert into #proctext(procedure_text) values( @cmd )
  21731. if @art_col > 0
  21732. begin
  21733.     select @cmd = N'
  21734. values ( '
  21735.     insert into #proctext(procedure_text) values( @cmd )
  21736.     insert into #proctext(procedure_text) values( @var_string )
  21737.     select @cmd = N' )
  21738. '
  21739.     insert into #proctext(procedure_text) values( @cmd )
  21740. end
  21741.  
  21742. -- set identity_insert off
  21743. if @identity_insert = 1
  21744. begin
  21745.     select @cmd = N'
  21746.     set identity_insert ' + @dest_owner + QUOTENAME(@dest_tabname) + ' off'
  21747.     insert into #proctext(procedure_text) values( @cmd )
  21748. end
  21749.  
  21750. --
  21751. -- If we are a part of queued publication then 
  21752. -- add the block delimiter
  21753. --
  21754. drop table #collisttab
  21755. if (@queued_check = 1)
  21756. begin
  21757.     select @cmd = N'
  21758.     END
  21759. END'
  21760. end
  21761. else
  21762.     select @cmd = N'
  21763. END'
  21764. insert into #proctext(procedure_text) values( @cmd )
  21765.  
  21766. -- send fragements to client
  21767.  
  21768. select procedure_text from #proctext order by c1 asc
  21769. END
  21770. go
  21771.  
  21772. EXEC dbo.sp_MS_marksystemobject sp_scriptinsproc
  21773. GO
  21774.  
  21775. ----------------------------------------------------
  21776. ---------------------------------------------------
  21777. print ''
  21778. print 'Creating procedure sp_scriptdelproc'
  21779. go
  21780.  
  21781. create procedure sp_scriptdelproc @artid int
  21782. as
  21783. declare @cmd          nvarchar(4000)
  21784. declare @dest_owner   nvarchar(255)
  21785. declare @dest_tabname sysname
  21786. declare @src_objid    int
  21787. declare @pkcolumns    binary(32)
  21788. declare @del_cmd      nvarchar(255)
  21789. declare @dest_proc    sysname
  21790. declare @this_col     int
  21791. declare @art_col      int
  21792. declare @isset        int, @pubid int
  21793.  
  21794. declare @typestring   nvarchar(255)
  21795. declare @spacer       nvarchar(10)
  21796.  
  21797. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  21798. begin
  21799.     raiserror (14155, 16, 1 )
  21800.     return 1
  21801. end
  21802.  
  21803. -------- create temp table for command fragments
  21804.  
  21805. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  21806.  
  21807. -- get sysarticles information
  21808.  
  21809. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  21810.        @src_objid = objid, @del_cmd = del_cmd, @pubid = pubid
  21811. from sysarticles
  21812. where artid = @artid
  21813.  
  21814. if @dest_owner is not null
  21815. begin
  21816.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  21817. end
  21818. else
  21819. begin
  21820.     select @dest_owner = N''
  21821. end
  21822.  
  21823. -------- get dest proc name
  21824.  
  21825. if( 1 != charindex( N'CALL', upper(@del_cmd) ) ) or @del_cmd is null
  21826. begin
  21827.     raiserror (14156, 16, 1 )
  21828.     return 1
  21829. end
  21830.  
  21831. select @dest_proc = substring( @del_cmd, 6, len( @del_cmd ) - 4 )
  21832. select @cmd = N'if exists (select * from sysobjects where type = ''P'' and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  21833. insert into #proctext(procedure_text) values( @cmd )
  21834. insert into #proctext(procedure_text) values( N'go' )
  21835. select @cmd = N'create procedure ' + QUOTENAME(@dest_proc)
  21836.  
  21837. -------- construct parameter list
  21838.  
  21839.  
  21840. select @art_col = 1
  21841. select @spacer = N' '
  21842.  
  21843. exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  21844.  
  21845. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  21846. select colid from syscolumns where id = @src_objid order by colid asc
  21847.  
  21848. OPEN hCColid
  21849.  
  21850. FETCH hCColid INTO @this_col
  21851.  
  21852. WHILE (@@fetch_status <> -1)
  21853. begin
  21854.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  21855.    if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid )
  21856.    begin
  21857.         if len( @cmd ) > 3000
  21858.         begin
  21859.         insert into #proctext(procedure_text) values( @cmd )
  21860.             select @cmd = N''
  21861.         end
  21862.  
  21863.         exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  21864.         select @cmd = @cmd + @spacer + N'@pkc' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  21865.         select @art_col = @art_col + 1
  21866.         select @spacer = N','
  21867.    end
  21868.     FETCH hCColid INTO @this_col
  21869. end
  21870.  
  21871. CLOSE hCColid
  21872. DEALLOCATE hCColid
  21873.  
  21874. -- save off 
  21875.  
  21876. insert into #proctext(procedure_text) values( @cmd )
  21877. insert into #proctext(procedure_text) values( N'as' )
  21878.  
  21879. ------- construct proc body
  21880.  
  21881. insert into #proctext(procedure_text) values( N'delete ' + @dest_owner + QUOTENAME(@dest_tabname) ) 
  21882.  
  21883. exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns
  21884.  
  21885. if exists (select * from syspublications where pubid = @pubid and allow_queued_tran = 0)
  21886.     exec dbo.sp_MSscript_missing_row_check
  21887. -- flush to client
  21888.  
  21889. select procedure_text from #proctext order by c1 asc
  21890.  
  21891.  
  21892. go
  21893.  
  21894. EXEC dbo.sp_MS_marksystemobject sp_scriptdelproc
  21895. GO
  21896.  
  21897. ----------------------------------------------------
  21898. ---------------------------------------------------
  21899. print ''
  21900. print 'Creating procedure sp_scriptxdelproc'
  21901. go
  21902.  
  21903. create procedure sp_scriptxdelproc @artid int
  21904. as
  21905. declare @cmd          nvarchar(4000)
  21906. declare @dest_owner   nvarchar(255)
  21907. declare @dest_tabname sysname
  21908. declare @src_objid    int
  21909. declare @columns    binary(32)
  21910. declare @pkcolumns    binary(32)
  21911. declare @del_cmd      nvarchar(255)
  21912. declare @dest_proc    sysname
  21913. declare @this_col     int
  21914. declare @art_col      int
  21915. declare @isset        int
  21916. declare @pubid          int
  21917. declare @typestring   nvarchar(255)
  21918. declare @spacer       nvarchar(10)
  21919. declare @queued_check bit
  21920.         ,@qwhere_string nvarchar(4000)
  21921.  
  21922. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  21923. begin
  21924.     raiserror (14155, 16, 1 )
  21925.     return 1
  21926. end
  21927.  
  21928. -------- create temp table for command fragments
  21929.  
  21930. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  21931.  
  21932. -- get sysarticles information
  21933.  
  21934. select @pubid = pubid, @dest_owner = dest_owner, @dest_tabname = dest_table, 
  21935.        @src_objid = objid, @del_cmd = del_cmd, @columns = columns
  21936. from sysarticles
  21937. where artid = @artid
  21938.  
  21939. if @dest_owner is not null
  21940. begin
  21941.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  21942. end
  21943. else
  21944. begin
  21945.     select @dest_owner = N''
  21946. end
  21947.  
  21948. -- Check if this is a queued publication
  21949. select @queued_check = ISNULL(allow_queued_tran, 0) 
  21950. from syspublications
  21951. where pubid = @pubid
  21952.  
  21953. -------- get dest proc name
  21954.  
  21955. if( 1 != charindex( N'XCALL', upper(@del_cmd) ) ) or @del_cmd is null
  21956. begin
  21957.     raiserror (14156, 16, 1 )
  21958.     return 1
  21959. end
  21960.  
  21961. select @dest_proc = substring( @del_cmd, 7, len( @del_cmd ) - 5 )
  21962. select @cmd = N'if exists (select * from sysobjects where type = ''P'' and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  21963. insert into #proctext(procedure_text) values( @cmd )
  21964. insert into #proctext(procedure_text) values( N'go' )
  21965. select @cmd = N'create procedure ' + QUOTENAME(@dest_proc)
  21966.  
  21967. -------- construct parameter list
  21968.  
  21969.  
  21970. select @art_col = 1
  21971. select @spacer = N' '
  21972.  
  21973. exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  21974.  
  21975. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  21976. select colid from syscolumns where id = @src_objid order by colid asc
  21977.  
  21978. OPEN hCColid
  21979.  
  21980. FETCH hCColid INTO @this_col
  21981.  
  21982. WHILE (@@fetch_status <> -1)
  21983. begin
  21984.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @columns
  21985.    if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  21986.    begin
  21987.         if len( @cmd ) > 3000
  21988.         begin
  21989.         insert into #proctext(procedure_text) values( @cmd )
  21990.             select @cmd = N''
  21991.         end
  21992.  
  21993.         exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  21994.         select @cmd = @cmd + @spacer + N'@c' + convert( nvarchar, @art_col ) + N' ' + @typestring 
  21995.  
  21996.         --
  21997.         -- Queued processing:if this is the row version column : need to add to where clause
  21998.         --
  21999.         if ((@queued_check = 1) and (col_name( @src_objid, @this_col) = N'msrepl_tran_version'))
  22000.             select @qwhere_string = N' and msrepl_tran_version = @c' + convert( nvarchar, @art_col )
  22001.  
  22002.         select @art_col = @art_col + 1
  22003.         select @spacer = N','
  22004.    end
  22005.    FETCH hCColid INTO @this_col
  22006. end
  22007.  
  22008. CLOSE hCColid
  22009. DEALLOCATE hCColid
  22010.  
  22011. -- save off 
  22012.  
  22013. insert into #proctext(procedure_text) values( @cmd )
  22014. insert into #proctext(procedure_text) values( N'as' )
  22015.  
  22016. ------- construct proc body
  22017.  
  22018. insert into #proctext(procedure_text) values( N'delete ' + @dest_owner + QUOTENAME(@dest_tabname) ) 
  22019.  
  22020. exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns, N'@c', @columns
  22021. if (@queued_check = 1)
  22022.     insert into #proctext(procedure_text) values( @qwhere_string )
  22023. else
  22024.     exec dbo.sp_MSscript_missing_row_check
  22025.  
  22026. -- flush to client
  22027.  
  22028. select procedure_text from #proctext order by c1 asc
  22029.  
  22030.  
  22031. go
  22032.  
  22033. EXEC dbo.sp_MS_marksystemobject sp_scriptxdelproc
  22034. GO
  22035.  
  22036. ----------------------------------------------------------------------------------------------
  22037. ----------------------------------------------------------------------------------------------
  22038. ----------------------------------------------------------------------------------------------
  22039.  
  22040. print ''
  22041. print 'Creating procedure sp_scriptupdproc'
  22042. go
  22043.  
  22044. create procedure sp_scriptupdproc @artid int
  22045. as
  22046. declare @cmd          nvarchar(4000)
  22047. declare @dest_owner   nvarchar(255)
  22048. declare @dest_tabname sysname
  22049. declare @src_objid    int
  22050. declare @artcolumns   binary(32)
  22051. declare @pkcolumns    binary(32)
  22052. declare @upd_cmd      nvarchar(255)
  22053. declare @dest_proc    sysname
  22054. declare @this_col     int
  22055. declare @art_col      int
  22056. declare @pkart_col    int
  22057. declare @isset        int
  22058. declare @pkcomputed   int
  22059. declare @typestring   nvarchar(255)
  22060. declare @spacer       nvarchar(10)
  22061. declare @pubid        int, @allow_queued_tran bit, @need_end bit
  22062.  
  22063. select @need_end = 0
  22064.  
  22065. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  22066. begin
  22067.     raiserror (14155, 16, 1 )
  22068.     return 1
  22069. end
  22070.  
  22071. -------- create temp table for command fragments
  22072.  
  22073. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  22074.  
  22075. -------- get sysarticles information
  22076.  
  22077. select @pubid = pubid, @dest_owner = dest_owner, @dest_tabname = dest_table, 
  22078.        @src_objid = objid, @artcolumns = columns, @upd_cmd = upd_cmd
  22079. from sysarticles
  22080. where artid = @artid
  22081.  
  22082. if @dest_owner is not null
  22083. begin
  22084.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  22085. end
  22086. else
  22087. begin
  22088.     select @dest_owner = N''
  22089. end
  22090.  
  22091. -------- get dest proc name
  22092.  
  22093. if( 1 != charindex( N'CALL', upper(@upd_cmd) ) ) or @upd_cmd is null
  22094. begin
  22095.     raiserror (14156, 16, 1 )
  22096.     return 1
  22097. end
  22098.  
  22099. select @allow_queued_tran = allow_queued_tran from syspublications where pubid = @pubid 
  22100.  
  22101. declare @keep_identity bit
  22102. if @allow_queued_tran = 1 and OBJECTPROPERTY(@src_objid, 'tablehasidentity') = 1
  22103.     select @keep_identity = 1
  22104. else
  22105.     select @keep_identity = 0
  22106.  
  22107. select @dest_proc = substring( @upd_cmd, 6, len( @upd_cmd ) - 4 )
  22108. select @cmd = N'if exists (select * from sysobjects where type = ''P'' and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  22109. insert into #proctext(procedure_text) values( @cmd )
  22110. insert into #proctext(procedure_text) values( N'go' )
  22111. insert into #proctext( procedure_text ) values (  N'create procedure ' + QUOTENAME(@dest_proc) + N' ')
  22112.  
  22113. -------- construct parameter list
  22114.  
  22115. exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  22116.  
  22117. exec dbo.sp_scriptupdateparams @src_objid, @artcolumns, @pkcolumns
  22118.  
  22119. insert into #proctext(procedure_text) values ( N'as' )
  22120.  
  22121. -------- now create the update statement
  22122.  
  22123. -- construct test to see if pk has changed 
  22124. -- only do this if the article has columns not included in the pk
  22125.  
  22126. exec @pkcomputed = sp_MSareallcolumnscomputed @src_objid, @pkcolumns
  22127.  
  22128. declare @pk_is_identity bit
  22129. select @pk_is_identity = 0
  22130.  
  22131. if @artcolumns != @pkcolumns and @pkcomputed = 0
  22132. begin
  22133.     select @cmd = N'if'
  22134.  
  22135.     select @art_col = 1
  22136.     select @pkart_col = 1
  22137.     select @spacer = ' '
  22138.  
  22139.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22140.     select colid from syscolumns where id = @src_objid order by colid asc
  22141.  
  22142.     OPEN hCColid
  22143.  
  22144.     FETCH hCColid INTO @this_col
  22145.  
  22146.     select @pk_is_identity = 1
  22147.     WHILE (@@fetch_status <> -1)
  22148.     begin
  22149.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22150.         if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  22151.         begin
  22152.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  22153.             if @isset != 0
  22154.             begin
  22155.                 if not (@keep_identity = 1 and 
  22156.                     columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  22157.                 begin
  22158.                     select @pk_is_identity = 0
  22159.                     select @cmd = @cmd + @spacer + N'@c'+convert( nvarchar, @art_col ) + N' = @pkc' + convert( nvarchar, @pkart_col ) 
  22160.                     select @spacer = N' and '
  22161.                     select @pkart_col = @pkart_col + 1
  22162.                     if len( @cmd ) > 3000
  22163.                     begin
  22164.                     insert into #proctext(procedure_text) values( @cmd )
  22165.                         select @cmd = N''
  22166.                     end
  22167.                 end
  22168.             end
  22169.             select @art_col = @art_col + 1
  22170.         end
  22171.         FETCH hCColid INTO @this_col
  22172.     end
  22173.  
  22174.     CLOSE hCColid
  22175.     DEALLOCATE hCColid
  22176.  
  22177.     if @pk_is_identity = 0
  22178.     begin
  22179.         insert into #proctext(procedure_text) values( @cmd )
  22180.  
  22181.         insert into #proctext(procedure_text) values( N'begin' )
  22182.  
  22183.         -- construct update if pk hasn't changed
  22184.  
  22185.         select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set'
  22186.  
  22187.         -- create SET clause
  22188.  
  22189.         select @art_col = 1
  22190.         select @spacer = N' '
  22191.  
  22192.         DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22193.         select colid from syscolumns where id = @src_objid order by colid asc
  22194.  
  22195.         OPEN hCColid
  22196.  
  22197.         FETCH hCColid INTO @this_col
  22198.         WHILE (@@fetch_status <> -1)
  22199.         begin
  22200.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22201.             if @isset != 0  and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  22202.             begin
  22203.                 exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  22204.                 if @isset = 0
  22205.                 begin
  22206.                     if not (@keep_identity = 1 and 
  22207.                         columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  22208.                     begin
  22209.                         select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = @c' + convert( nvarchar, @art_col ) 
  22210.                         select @spacer = N','
  22211.  
  22212.                         if len( @cmd ) > 3000
  22213.                         begin
  22214.                             insert into #proctext(procedure_text) values( @cmd )
  22215.                             select @cmd = N''
  22216.                         end
  22217.                     end
  22218.                 end
  22219.                 select @art_col = @art_col + 1
  22220.             end
  22221.             FETCH hCColid INTO @this_col
  22222.         end
  22223.         CLOSE hCColid
  22224.         DEALLOCATE hCColid
  22225.  
  22226.         insert into #proctext(procedure_text) values( @cmd )
  22227.  
  22228.         exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns
  22229.  
  22230.         if @allow_queued_tran <> 1
  22231.             exec dbo.sp_MSscript_missing_row_check
  22232.  
  22233.         insert into #proctext(procedure_text) values( N'end' )
  22234.         insert into #proctext(procedure_text) values( N'else' )
  22235.         insert into #proctext(procedure_text) values( N'begin' )
  22236.  
  22237.         select @need_end = 1
  22238.  
  22239.     end
  22240. end -- end if artcols != pkcols
  22241.  
  22242.  
  22243. -- construct update if pk has changed
  22244.  
  22245. select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set'
  22246.  
  22247. -- create SET clause
  22248.  
  22249. select @art_col = 1
  22250. select @spacer = N' '
  22251.  
  22252. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22253. select colid from syscolumns where id = @src_objid order by colid asc
  22254.  
  22255. OPEN hCColid
  22256.  
  22257. FETCH hCColid INTO @this_col
  22258. WHILE (@@fetch_status <> -1)
  22259. begin
  22260.     exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22261.     if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  22262.     begin
  22263.         if not (@keep_identity = 1 and 
  22264.             columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  22265.         begin
  22266.             select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = @c' + convert( nvarchar, @art_col ) 
  22267.             select @spacer = N','
  22268.  
  22269.             if len( @cmd ) > 3000
  22270.             begin
  22271.             insert into #proctext(procedure_text) values( @cmd )
  22272.                 select @cmd = N''
  22273.             end
  22274.         end
  22275.         select @art_col = @art_col + 1
  22276.     end
  22277.     FETCH hCColid INTO @this_col
  22278. end
  22279.  
  22280. CLOSE hCColid
  22281. DEALLOCATE hCColid
  22282.  
  22283. insert into #proctext(procedure_text) values( @cmd )
  22284.  
  22285. exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns
  22286.  
  22287. if @allow_queued_tran <> 1
  22288.     exec dbo.sp_MSscript_missing_row_check
  22289.  
  22290. if @need_end = 1
  22291.     insert into #proctext(procedure_text) values( N'end' )
  22292. -- flush to client
  22293.  
  22294. select procedure_text from #proctext order by c1 asc
  22295.  
  22296. go
  22297.  
  22298. EXEC dbo.sp_MS_marksystemobject sp_scriptupdproc
  22299. GO
  22300.  
  22301. --------------------------------------------------------------------------
  22302. --------------------------------------------------------------------------
  22303.  
  22304. print ''
  22305. print 'Creating procedure sp_scriptmappedupdproc'
  22306. go
  22307.  
  22308. create procedure sp_scriptmappedupdproc @artid int
  22309. as
  22310. declare @cmd          nvarchar(4000)
  22311. declare @dest_owner   nvarchar(255)
  22312. declare @dest_tabname sysname
  22313. declare @src_objid    int
  22314. declare @artcolumns   binary(32)
  22315. declare @pkcolumns    binary(32)
  22316. declare @upd_cmd      nvarchar(255)
  22317. declare @dest_proc    sysname
  22318. declare @art_cols     int
  22319. declare @this_col     int
  22320. declare @art_col      int
  22321. declare @pkart_col    int
  22322. declare @isset        int
  22323. declare @bytestr      nvarchar(10)
  22324. declare @bitstr       nvarchar(10)
  22325. declare @typestring   nvarchar(255)
  22326. declare @spacer       nvarchar(10)
  22327. declare @update_created  bit
  22328. declare @pkcomputed   int
  22329. declare @pubid        int, @allow_queued_tran bit
  22330.  
  22331. select @update_created     = 0
  22332.  
  22333. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  22334. begin
  22335.     raiserror (14155, 16, 1 )
  22336.     return 1
  22337. end
  22338.  
  22339. -------- create temp table for command fragments
  22340.  
  22341. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  22342.  
  22343. -------- get sysarticles information
  22344.  
  22345. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  22346.        @src_objid = objid, @artcolumns = columns, @upd_cmd = upd_cmd,
  22347.        @pubid = pubid
  22348. from sysarticles
  22349. where artid = @artid
  22350.  
  22351. if @dest_owner is not null
  22352. begin
  22353.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  22354. end
  22355. else
  22356. begin
  22357.     select @dest_owner = N''
  22358. end
  22359.  
  22360. -------- get dest proc name
  22361.  
  22362. if( 1 != charindex( N'MCALL', upper(@upd_cmd) ) ) or @upd_cmd is null
  22363. begin
  22364.     raiserror (14156, 16, 1 )
  22365.     return 1
  22366. end
  22367.  
  22368. select @allow_queued_tran = allow_queued_tran from syspublications where pubid = @pubid 
  22369.  
  22370. declare @keep_identity bit
  22371. if @allow_queued_tran = 1 and OBJECTPROPERTY(@src_objid, 'tablehasidentity') = 1
  22372.     select @keep_identity = 1
  22373. else
  22374.     select @keep_identity = 0
  22375.  
  22376. select @dest_proc = substring( @upd_cmd, 7, len( @upd_cmd ) - 5 )
  22377. select @cmd = N'if exists (select * from sysobjects where type = ''P''  and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  22378. insert into #proctext(procedure_text) values( @cmd )
  22379. insert into #proctext(procedure_text) values( N'go' )
  22380. insert into #proctext( procedure_text ) values ( N'create procedure ' + QUOTENAME(@dest_proc) + N' ' )
  22381.   
  22382.  
  22383. -------- construct parameter list
  22384.  
  22385. exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  22386.  
  22387. exec dbo.sp_scriptupdateparams @src_objid, @artcolumns, @pkcolumns
  22388.  
  22389. ----- add changed data bitmap
  22390.  
  22391. select @art_col = 1
  22392.  
  22393.  
  22394. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22395. select colid from syscolumns where id = @src_objid order by colid asc
  22396.  
  22397. OPEN hCColid
  22398.  
  22399. FETCH hCColid INTO @this_col
  22400.  
  22401. WHILE (@@fetch_status <> -1)
  22402. begin
  22403.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22404.    if @isset != 0 and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  22405.    begin
  22406.         select @art_col = @art_col + 1
  22407.    end
  22408.    FETCH hCColid INTO @this_col
  22409. end
  22410. CLOSE hCColid
  22411. DEALLOCATE hCColid
  22412.  
  22413. -- Note that bitmap size is based on number of article columns
  22414. -- (computed by loop above) not source table columns
  22415.  
  22416. select @cmd = N',@bitmap binary(' + convert(nvarchar,1+(@art_col-1) / 8) + N')'
  22417.  
  22418. insert into #proctext(procedure_text) values( @cmd )
  22419. insert into #proctext(procedure_text) values( N'as' )
  22420.  
  22421.  
  22422. -- construct IF statement to examine colbitmap and determine if a 
  22423. -- primary key column has been updated.  
  22424.  
  22425. -- do this only if the article contains columns not included in the pk
  22426. -- and at least one of the columns in the PK is real ( i.e. not computed )
  22427.  
  22428. -- note that if all the article columns are PK columns, we will
  22429. -- construct the 'update all columns including PK columns' statement
  22430. -- w/o a preceeding IF, and we will NOT construct the 'only update non-pk columns' 
  22431. -- part of the procedure
  22432.  
  22433. -- also note that this is pretty much worthless since 7.0 and above are
  22434. -- guaranteed to NEVER generate an UPDATE if a PK columns is updated... oh well.
  22435. declare @pk_is_identity bit
  22436. select @pk_is_identity = 0
  22437.  
  22438. exec @pkcomputed = sp_MSareallcolumnscomputed @src_objid, @pkcolumns
  22439.  
  22440. if @artcolumns != @pkcolumns and @pkcomputed = 0
  22441. begin
  22442.     select @art_col = 1
  22443.     select @spacer = N' '
  22444.  
  22445.     select @cmd = N'if'
  22446.  
  22447.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22448.     select colid from syscolumns where id = @src_objid order by colid asc
  22449.  
  22450.     OPEN hCColid
  22451.  
  22452.     FETCH hCColid INTO @this_col
  22453.  
  22454.     select @pk_is_identity = 1
  22455.  
  22456.     WHILE (@@fetch_status <> -1)
  22457.     begin
  22458.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22459.         if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  22460.         begin 
  22461.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  22462.             if @isset != 0
  22463.             begin
  22464.                 if not (@keep_identity = 1 and 
  22465.                     columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  22466.                 begin
  22467.                     select @pk_is_identity = 0
  22468.                     select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 )
  22469.                     select @bitstr =  convert( nvarchar, power(2, (@art_col-1) % 8 ) )
  22470.  
  22471.                     select @cmd = @cmd + @spacer + N'substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr +  
  22472.                              N' = ' + @bitstr 
  22473.                 
  22474.                     select @spacer = N' or '
  22475.  
  22476.                     if len( @cmd ) > 3000
  22477.                     begin
  22478.                         insert into #proctext(procedure_text) values( @cmd )
  22479.                         select @cmd = N''
  22480.                     end
  22481.                 end
  22482.             end
  22483.             select @art_col = @art_col + 1
  22484.         end
  22485.         FETCH hCColid INTO @this_col
  22486.     end
  22487.     CLOSE hCColid
  22488.     DEALLOCATE hCColid
  22489.  
  22490.     if @pk_is_identity = 0
  22491.         insert into #proctext(procedure_text) values( @cmd )
  22492.  
  22493. end  -- if artcolumns != pkcolumns
  22494.  
  22495. -- construct update statement including PK columns
  22496.  
  22497. insert into #proctext(procedure_text) values( N'begin' )
  22498.  
  22499. insert into #proctext(procedure_text) values( N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set' )
  22500.  
  22501. -- create SET clause consisting of CASE statements
  22502.  
  22503. select @art_col = 1
  22504. select @spacer = N''
  22505.  
  22506. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22507. select colid from syscolumns where id = @src_objid order by colid asc
  22508.  
  22509. OPEN hCColid
  22510.  
  22511. FETCH hCColid INTO @this_col
  22512.  
  22513. WHILE (@@fetch_status <> -1)
  22514. begin
  22515.     exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22516.     if @isset != 0  and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  22517.     begin
  22518.         if not (@keep_identity = 1 and 
  22519.             columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  22520.         begin
  22521.             select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 )
  22522.             select @bitstr =  convert( nvarchar, power(2, (@art_col-1) % 8 ) )
  22523.  
  22524.             insert into #proctext(procedure_text) values (
  22525.                  @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = case substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr +  
  22526.                  N' when ' + @bitstr + N' then ' + N'@c'+ convert( nvarchar, @art_col ) + 
  22527.                  N' else ' + QUOTENAME(col_name( @src_objid, @this_col)) + N' end' )
  22528.  
  22529.             select @spacer = ',' 
  22530.         end
  22531.  
  22532.         select @art_col = @art_col + 1
  22533.     end
  22534.     FETCH hCColid INTO @this_col
  22535. end
  22536. CLOSE hCColid
  22537. DEALLOCATE hCColid
  22538.  
  22539. -- create where clause
  22540.  
  22541. exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns
  22542.  
  22543. if @allow_queued_tran <> 1
  22544.     exec dbo.sp_MSscript_missing_row_check
  22545.  
  22546. -- construct UPDATE that does not set PK cols
  22547. -- only do this if the article contains columns that are not included
  22548. -- in the pk
  22549.  
  22550. if @artcolumns != @pkcolumns  and @pkcomputed = 0 and @pk_is_identity = 0
  22551. begin
  22552.  
  22553.     -- create SET clause consisting of CASE statements
  22554.  
  22555.     select @art_col = 1
  22556.     select @spacer = N''
  22557.  
  22558.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22559.     select colid from syscolumns where id = @src_objid order by colid asc
  22560.  
  22561.     OPEN hCColid
  22562.  
  22563.     FETCH hCColid INTO @this_col
  22564.  
  22565.     WHILE (@@fetch_status <> -1)
  22566.     begin
  22567.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22568.         if @isset != 0  and EXISTS (select name from syscolumns where colid=@this_col and iscomputed<>1 and id = @src_objid)
  22569.         begin
  22570.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns 
  22571.             if @isset = 0 
  22572.             begin
  22573.                 if not (@keep_identity = 1 and 
  22574.                     columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  22575.                 begin
  22576.                     if (@update_created = 0)
  22577.                     begin
  22578.                         insert into #proctext(procedure_text) values( N'end' )
  22579.                         insert into #proctext(procedure_text) values( N'else' )
  22580.                         insert into #proctext(procedure_text) values( N'begin' )
  22581.                         insert into #proctext(procedure_text) values( N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set' )
  22582.                         select @update_created = 1
  22583.                     end
  22584.                     select @bytestr = convert( nvarchar, 1 + (@art_col-1) / 8 )
  22585.                     select @bitstr =  convert( nvarchar, power(2, (@art_col-1) % 8 ) )
  22586.  
  22587.                     insert into #proctext(procedure_text) values (
  22588.                          @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + N' = case substring(@bitmap,' + @bytestr + N',1) & ' + @bitstr +  
  22589.                          N' when ' + @bitstr + N' then ' + N'@c'+ convert( nvarchar, @art_col ) + 
  22590.                          N' else ' + QUOTENAME(col_name( @src_objid, @this_col)) + N' end' )
  22591.  
  22592.                     select @spacer = ',' 
  22593.                 end
  22594.             end
  22595.             select @art_col = @art_col + 1
  22596.         end
  22597.            FETCH hCColid INTO @this_col
  22598.     end
  22599.     CLOSE hCColid
  22600.     DEALLOCATE hCColid
  22601.  
  22602.     if @update_created = 1
  22603.     begin
  22604.         exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns
  22605.         if @allow_queued_tran <> 1
  22606.             exec dbo.sp_MSscript_missing_row_check
  22607.     end
  22608.  
  22609. end
  22610.  
  22611. insert into #proctext(procedure_text) values( N'end' )
  22612. select procedure_text from #proctext order by c1 asc
  22613.  
  22614. go
  22615.  
  22616. EXEC dbo.sp_MS_marksystemobject sp_scriptmappedupdproc
  22617. GO
  22618.  
  22619. ----------------------------------------------------------------------------------------------
  22620. ----------------------------------------------------------------------------------------------
  22621.  
  22622. print ''
  22623. print 'Creating procedure sp_scriptxupdproc'
  22624. go
  22625.  
  22626. create procedure sp_scriptxupdproc @artid int
  22627. as
  22628. declare @cmd          nvarchar(4000),
  22629.         @dest_owner   nvarchar(255),
  22630.         @dest_tabname sysname,
  22631.         @src_objid    int,
  22632.         @artcolumns   binary(32),
  22633.         @pkcolumns    binary(32),
  22634.         @upd_cmd      nvarchar(255),
  22635.         @dest_proc    sysname,
  22636.         @this_col     int,
  22637.         @art_col      int,
  22638.         --@pkart_col    int,
  22639.         @isset        int,
  22640.         @pkcomputed   int,
  22641.         @typestring   nvarchar(255),
  22642.         @spacer       nvarchar(10),
  22643.         @pubid          int, 
  22644.         @param_count  int
  22645.         ,@queued_check bit, @exists_else bit
  22646.         ,@qwhere_string nvarchar(4000)
  22647.  
  22648. set nocount on
  22649. if not exists( select * from sysarticles where artid = @artid AND (type & 1) = 1 )
  22650. begin
  22651.     raiserror (14155, 16, 1 )
  22652.     return 1
  22653. end
  22654.  
  22655. select @exists_else = 0
  22656.  
  22657. -------- create temp table for command fragments
  22658.  
  22659. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default null)
  22660.  
  22661. -------- get sysarticles information
  22662.  
  22663. select @pubid = pubid, @dest_owner = dest_owner, @dest_tabname = dest_table, 
  22664.        @src_objid = objid, @artcolumns = columns, @upd_cmd = upd_cmd
  22665. from sysarticles
  22666. where artid = @artid
  22667.  
  22668. if @dest_owner is not null
  22669. begin
  22670.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  22671. end
  22672. else
  22673. begin
  22674.     select @dest_owner = N''
  22675. end
  22676.  
  22677. -- Check if this is a queued publication
  22678. select @queued_check = ISNULL(allow_queued_tran, 0) 
  22679. from syspublications
  22680. where pubid = @pubid
  22681.  
  22682. -------- get dest proc name
  22683.  
  22684. if( 1 != charindex( N'XCALL', upper(@upd_cmd) ) ) or @upd_cmd is null
  22685. begin
  22686.     raiserror (14156, 16, 1 )
  22687.     return 1
  22688. end
  22689.  
  22690. declare @keep_identity bit
  22691. if exists (select * from syspublications where pubid = @pubid and
  22692.     allow_queued_tran = 1) and OBJECTPROPERTY(@src_objid, 'tablehasidentity') = 1
  22693.     select @keep_identity = 1
  22694. else
  22695.     select @keep_identity = 0
  22696.  
  22697. select @dest_proc = substring( @upd_cmd, 7, len( @upd_cmd ) - 5 )
  22698. select @cmd = N'if exists (select * from sysobjects where type = ''P''  and name = ''' + replace(@dest_proc, N'''', N'''''') + N''')  drop proc ' + QUOTENAME(@dest_proc)
  22699. insert into #proctext(procedure_text) values( @cmd )
  22700. insert into #proctext(procedure_text) values( N'go' )
  22701. insert into #proctext( procedure_text ) values (  N'create procedure ' + QUOTENAME(@dest_proc) + N' ')
  22702.  
  22703. -------- construct parameter list
  22704.  
  22705. exec dbo.sp_getarticlepkcolbitmap @src_objid, @pkcolumns output
  22706.  
  22707. -- Send null as @pkcolumns. We don't need pk parameters.
  22708. exec dbo.sp_scriptupdateparams @src_objid, @artcolumns, NULL, @param_count output
  22709.  
  22710. insert into #proctext(procedure_text) values ( N'as' )
  22711.  
  22712. -------- now create the update statement
  22713.  
  22714. -- construct test to see if pk has changed 
  22715. -- only do this if the article has columns not included in the pk
  22716.  
  22717. exec @pkcomputed = sp_MSareallcolumnscomputed @src_objid, @pkcolumns
  22718.  
  22719. declare @pk_is_identity bit
  22720. select @pk_is_identity = 0
  22721.  
  22722. if @artcolumns != @pkcolumns and @pkcomputed = 0
  22723. begin
  22724.     select @cmd = N'if'
  22725.  
  22726.     select @art_col = 1
  22727.     --select @pkart_col = 1
  22728.     select @spacer = ' '
  22729.  
  22730.     DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22731.     select colid from syscolumns where id = @src_objid order by colid asc
  22732.  
  22733.     OPEN hCColid
  22734.  
  22735.     FETCH hCColid INTO @this_col
  22736.  
  22737.     select @pk_is_identity = 1
  22738.     WHILE (@@fetch_status <> -1)
  22739.     begin
  22740.         exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22741.         if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  22742.         begin
  22743.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  22744.             if @isset != 0
  22745.             begin
  22746.                 if not (@keep_identity = 1 and 
  22747.                     columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  22748.                 begin
  22749.                     select @pk_is_identity = 0
  22750.                     select @cmd = @cmd + @spacer + N'@c'+convert( nvarchar, @art_col + @param_count/2) + 
  22751.                         N' = @c' + convert( nvarchar, @art_col ) 
  22752.                     select @spacer = N' and '
  22753.                     --select @pkart_col = @pkart_col + 1
  22754.                     if len( @cmd ) > 3000
  22755.                     begin
  22756.                     insert into #proctext(procedure_text) values( @cmd )
  22757.                         select @cmd = N''
  22758.                     end
  22759.                 end
  22760.             end
  22761.             select @art_col = @art_col + 1
  22762.         end
  22763.         FETCH hCColid INTO @this_col
  22764.     end
  22765.  
  22766.     CLOSE hCColid
  22767.     DEALLOCATE hCColid
  22768.  
  22769.     if @pk_is_identity = 0
  22770.     begin
  22771.         insert into #proctext(procedure_text) values( @cmd )
  22772.  
  22773.         insert into #proctext(procedure_text) values( N'begin' )
  22774.  
  22775.         -- construct update if pk hasn't changed
  22776.         -- We know that there would be a least one column for the update below, even if
  22777.         -- the columns outside the pk are identity or timestamp. Since identity and timestamp
  22778.         -- will be mapped off unless it is queued tran. In that case, we have 'msrepl_tran_version'
  22779.         select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set'
  22780.  
  22781.         -- create SET clause
  22782.  
  22783.         select @art_col = 1
  22784.         select @spacer = N' '
  22785.  
  22786.         DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22787.         select colid from syscolumns where id = @src_objid order by colid asc
  22788.  
  22789.         OPEN hCColid
  22790.  
  22791.         FETCH hCColid INTO @this_col
  22792.         WHILE (@@fetch_status <> -1)
  22793.         begin
  22794.             exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22795.             if @isset != 0  and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  22796.             begin
  22797.                 exec @isset = dbo.sp_isarticlecolbitset @this_col, @pkcolumns
  22798.                 if @isset = 0
  22799.                 begin
  22800.                     if not (@keep_identity = 1 and 
  22801.                         columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  22802.                     begin
  22803.                         select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + 
  22804.                             N' = @c' + convert( nvarchar, @art_col + @param_count/2) 
  22805.                         select @spacer = N','
  22806.  
  22807.                         if len( @cmd ) > 3000
  22808.                         begin
  22809.                             insert into #proctext(procedure_text) values( @cmd )
  22810.                             select @cmd = N''
  22811.                         end
  22812.  
  22813.                         --
  22814.                         -- Queued processing:if this is the row version column : need to add to where clause
  22815.                         --
  22816.                         if ((@queued_check = 1) and (col_name( @src_objid, @this_col) = N'msrepl_tran_version'))
  22817.                             select @qwhere_string = N' and msrepl_tran_version = @c' + convert( nvarchar, @art_col )                        
  22818.                     end
  22819.                 end
  22820.                 select @art_col = @art_col + 1
  22821.             end
  22822.             FETCH hCColid INTO @this_col
  22823.         end
  22824.         CLOSE hCColid
  22825.         DEALLOCATE hCColid
  22826.  
  22827.         insert into #proctext(procedure_text) values( @cmd )
  22828.  
  22829.         exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns, N'@c', @artcolumns
  22830.         if (@queued_check = 1)
  22831.             insert into #proctext(procedure_text) values( @qwhere_string )
  22832.         else
  22833.             exec dbo.sp_MSscript_missing_row_check
  22834.  
  22835.         insert into #proctext(procedure_text) values( N'end' )
  22836.         insert into #proctext(procedure_text) values( N'else' )
  22837.         insert into #proctext(procedure_text) values( N'begin' )
  22838.  
  22839.         select @exists_else = 1
  22840.  
  22841.     end
  22842. end -- end if artcols != pkcols
  22843.  
  22844.  
  22845. -- construct update if pk has changed
  22846. select @cmd = N'update ' + @dest_owner + QUOTENAME(@dest_tabname) + N' set'
  22847.  
  22848. -- create SET clause
  22849.  
  22850. select @art_col = 1
  22851. select @spacer = N' '
  22852.  
  22853. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  22854. select colid from syscolumns where id = @src_objid order by colid asc
  22855.  
  22856. OPEN hCColid
  22857.  
  22858. FETCH hCColid INTO @this_col
  22859. WHILE (@@fetch_status <> -1)
  22860. begin
  22861.     exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  22862.     if @isset != 0 and EXISTS (select name from syscolumns where id=@src_objid and @this_col=colid and iscomputed<>1)
  22863.     begin
  22864.         if not (@keep_identity = 1 and 
  22865.             columnproperty(@src_objid, col_name( @src_objid, @this_col), 'IsIdentity') = 1)
  22866.         begin
  22867.             select @cmd = @cmd + @spacer + QUOTENAME(col_name( @src_objid, @this_col)) + 
  22868.                 N' = @c' + convert( nvarchar, @art_col + @param_count/2 ) 
  22869.             select @spacer = N','
  22870.  
  22871.             if len( @cmd ) > 3000
  22872.             begin
  22873.             insert into #proctext(procedure_text) values( @cmd )
  22874.                 select @cmd = N''
  22875.             end
  22876.  
  22877.             --
  22878.             -- Queued processing:if this is the row version column : need to add to where clause
  22879.             --
  22880.             if ((@queued_check = 1) and (col_name( @src_objid, @this_col) = N'msrepl_tran_version'))
  22881.                 select @qwhere_string = N' and msrepl_tran_version = @c' + convert( nvarchar, @art_col )                        
  22882.         end
  22883.         select @art_col = @art_col + 1
  22884.     end
  22885.     FETCH hCColid INTO @this_col
  22886. end
  22887.  
  22888. CLOSE hCColid
  22889. DEALLOCATE hCColid
  22890.  
  22891. insert into #proctext(procedure_text) values( @cmd )
  22892.  
  22893. exec dbo.sp_scriptpkwhereclause @src_objid, @pkcolumns, N'@c', @artcolumns
  22894. if (@queued_check = 1)
  22895.     insert into #proctext(procedure_text) values( @qwhere_string ) 
  22896. else
  22897.     exec dbo.sp_MSscript_missing_row_check
  22898.  
  22899. if @exists_else = 1
  22900.     insert into #proctext(procedure_text) values( N'end' )
  22901.  
  22902. -- flush to client
  22903.  
  22904. select procedure_text from #proctext order by c1 asc
  22905.  
  22906. go
  22907.  
  22908. EXEC dbo.sp_MS_marksystemobject sp_scriptxupdproc
  22909. GO
  22910.  
  22911. --------------------------------------------------------------------------
  22912. --------------------------------------------------------------------------
  22913.  
  22914. print ''
  22915. print 'Creating procedure sp_MSscriptmvastablenci'
  22916. go
  22917.  
  22918. create procedure sp_MSscriptmvastablenci @artid int
  22919. as
  22920. declare @cmd          nvarchar(4000)
  22921. declare @dest_owner   nvarchar(255)
  22922. declare @dest_tabname sysname
  22923. declare @src_objid    int
  22924. declare @constraint_name  sysname
  22925. declare @spacer          nvarchar(1)
  22926. declare @srcobj          nvarchar(1000)
  22927. declare @colname      sysname
  22928. declare @indkey          int
  22929. declare @indid          int
  22930. declare @status          int
  22931. declare @unique          nvarchar(10)
  22932. declare @cmd_sep      nvarchar(10)
  22933.  
  22934. -------- create temp table for command fragments
  22935.  
  22936. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  22937.  
  22938. -------- get sysarticles information
  22939.  
  22940. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  22941.        @src_objid = objid
  22942. from sysarticles
  22943. where artid = @artid
  22944.  
  22945. if @dest_owner is not null
  22946. begin
  22947.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  22948. end
  22949. else
  22950. begin
  22951.     select @dest_owner = N''
  22952. end
  22953.  
  22954. select @srcobj = QUOTENAME( USER_NAME(OBJECTPROPERTY(@src_objid,'OwnerId'))) collate database_default + N'.' + QUOTENAME(object_name(@src_objid)) collate database_default
  22955. select @cmd_sep = N''
  22956.  
  22957. DECLARE hCIdx CURSOR LOCAL FAST_FORWARD FOR
  22958. select name, indid, status from sysindexes where id = @src_objid and indid > 1 order by indid asc
  22959.  
  22960. OPEN hCIdx
  22961. FETCH hCIdx INTO @constraint_name, @indid, @status
  22962.  
  22963. WHILE (@@fetch_status <> -1)
  22964. begin
  22965.     if @status & 2 = 2
  22966.     begin
  22967.         select @unique = N' unique '
  22968.     end
  22969.     else
  22970.     begin
  22971.         select @unique = N' '
  22972.     end
  22973.  
  22974.     insert into #proctext(procedure_text) values( @cmd_sep )
  22975.     select @cmd_sep = N'GO'
  22976.  
  22977.     select @cmd = N'create' + @unique + N'nonclustered index ' + QUOTENAME(@constraint_name) + N' on ' +@dest_owner + QUOTENAME(@dest_tabname) + N'('
  22978.     insert into #proctext(procedure_text) values( @cmd )
  22979.  
  22980.     select @spacer = N' '
  22981.     select @cmd = N''
  22982.  
  22983.     select @indkey = 1
  22984.     while (@indkey <= 16)
  22985.     begin    
  22986.         select @colname = index_col(@srcobj, @indid, @indkey)
  22987.         if (@colname is null)
  22988.         begin
  22989.             select @indkey = 16
  22990.         end
  22991.         else
  22992.         begin
  22993.             select @cmd = @cmd + @spacer + QUOTENAME(@colname)
  22994.             select @spacer = N','
  22995.  
  22996.             if len( @cmd ) > 3000
  22997.             begin
  22998.                 insert into #proctext(procedure_text) values( @cmd )
  22999.                 select @cmd = N''
  23000.             end
  23001.         end
  23002.         select @indkey = @indkey + 1
  23003.     end
  23004.  
  23005.     insert into #proctext(procedure_text) values( @cmd )
  23006.     insert into #proctext(procedure_text) values( N')' )
  23007.     
  23008.     FETCH hCIdx INTO @constraint_name, @indid, @status
  23009. end
  23010.  
  23011. CLOSE hCIdx
  23012. DEALLOCATE hCIdx
  23013. select procedure_text from #proctext order by c1 asc
  23014.  
  23015. go
  23016. EXEC dbo.sp_MS_marksystemobject sp_MSscriptmvastablenci
  23017. GO
  23018.  
  23019. print ''
  23020. print 'Creating procedure sp_MSscriptmvastablepkc'
  23021. go
  23022.  
  23023. create procedure sp_MSscriptmvastablepkc @artid int
  23024. as
  23025. declare @cmd          nvarchar(4000)
  23026. declare @dest_owner   nvarchar(255)
  23027. declare @dest_tabname sysname
  23028. declare @src_objid    int
  23029. declare @constraint_name  sysname
  23030. declare @spacer          nvarchar(1)
  23031. declare @srcobj          nvarchar(1000)
  23032. declare @colname      sysname
  23033. declare @indkey          int
  23034. declare @indid          int
  23035.  
  23036. -------- create temp table for command fragments
  23037.  
  23038. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  23039.  
  23040. -------- get sysarticles information
  23041.  
  23042. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  23043.        @src_objid = objid
  23044. from sysarticles
  23045. where artid = @artid
  23046.  
  23047. if @dest_owner is not null
  23048. begin
  23049.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  23050. end
  23051. else
  23052. begin
  23053.     select @dest_owner = N''
  23054. end
  23055.  
  23056. select @srcobj = QUOTENAME( USER_NAME(OBJECTPROPERTY(@src_objid,'OwnerId'))) collate database_default + N'.' + QUOTENAME(object_name(@src_objid)) collate database_default
  23057.  
  23058. select @constraint_name = name, @indid = indid from sysindexes where id = @src_objid and status & 16 <> 0
  23059.  
  23060. 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 ('
  23061. insert into #proctext(procedure_text) values( @cmd )
  23062.  
  23063. select @spacer = N' '
  23064. select @cmd = N''
  23065.  
  23066. select @indkey = 1
  23067. while (@indkey <= 16)
  23068. begin    
  23069.     select @colname = index_col(@srcobj, @indid, @indkey)
  23070.     if (@colname is null)
  23071.     begin
  23072.         select @indkey = 16
  23073.     end
  23074.     else
  23075.     begin
  23076.         select @cmd = @cmd + @spacer + QUOTENAME(@colname) collate database_default
  23077.         select @spacer = N','
  23078.  
  23079.         if len( @cmd ) > 3000
  23080.         begin
  23081.             insert into #proctext(procedure_text) values( @cmd )
  23082.             select @cmd = N''
  23083.         end
  23084.     end
  23085.     select @indkey = @indkey + 1
  23086. end
  23087.  
  23088. insert into #proctext(procedure_text) values( @cmd )
  23089.  
  23090. insert into #proctext(procedure_text) values( N')' )
  23091.  
  23092. select procedure_text from #proctext order by c1 asc
  23093.  
  23094. go
  23095. EXEC dbo.sp_MS_marksystemobject sp_MSscriptmvastablepkc
  23096. GO
  23097.  
  23098. print ''
  23099. print 'Creating procedure sp_MSscriptmvastableidx'
  23100. go
  23101.  
  23102. create procedure sp_MSscriptmvastableidx @artid int
  23103. as
  23104. declare @cmd          nvarchar(4000)
  23105. declare @dest_owner   nvarchar(255)
  23106. declare @dest_tabname sysname
  23107. declare @src_objid    int
  23108. declare @constraint_name  sysname
  23109. declare @spacer          nvarchar(1)
  23110. declare @srcobj          nvarchar(1000)
  23111. declare @colname      sysname
  23112. declare @indkey          int
  23113. declare @indid          int
  23114.  
  23115. -------- create temp table for command fragments
  23116.  
  23117. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  23118.  
  23119. -------- get sysarticles information
  23120.  
  23121. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  23122.        @src_objid = objid
  23123. from sysarticles
  23124. where artid = @artid
  23125.  
  23126. if @dest_owner is not null
  23127. begin
  23128.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  23129. end
  23130. else
  23131. begin
  23132.     select @dest_owner = N''
  23133. end
  23134.  
  23135. select @srcobj = QUOTENAME( USER_NAME(OBJECTPROPERTY(@src_objid,'OwnerId'))) collate database_default + N'.' + QUOTENAME(object_name(@src_objid)) collate database_default
  23136.  
  23137. select @constraint_name = name, @indid = indid from sysindexes where id = @src_objid and status & 16 <> 0
  23138.  
  23139. select @cmd = N'create unique clustered index ' + QUOTENAME(@constraint_name) + N' on ' +@dest_owner + QUOTENAME(@dest_tabname) + N'('
  23140. insert into #proctext(procedure_text) values( @cmd )
  23141.  
  23142. select @spacer = N' '
  23143. select @cmd = N''
  23144.  
  23145. select @indkey = 1
  23146. while (@indkey <= 16)
  23147. begin    
  23148.     select @colname = index_col(@srcobj, @indid, @indkey)
  23149.     if (@colname is null)
  23150.     begin
  23151.         select @indkey = 16
  23152.     end
  23153.     else
  23154.     begin
  23155.         select @cmd = @cmd + @spacer + QUOTENAME(@colname)
  23156.         select @spacer = N','
  23157.  
  23158.         if len( @cmd ) > 3000
  23159.         begin
  23160.             insert into #proctext(procedure_text) values( @cmd )
  23161.             select @cmd = N''
  23162.         end
  23163.     end
  23164.     select @indkey = @indkey + 1
  23165. end
  23166.  
  23167. insert into #proctext(procedure_text) values( @cmd )
  23168.  
  23169. insert into #proctext(procedure_text) values( N')' )
  23170.  
  23171. select procedure_text from #proctext order by c1 asc
  23172.  
  23173. go
  23174. EXEC dbo.sp_MS_marksystemobject sp_MSscriptmvastableidx
  23175. GO
  23176.  
  23177.  
  23178. print ''
  23179. print 'Creating procedure sp_MSscriptmvastable'
  23180. go
  23181.  
  23182. create procedure sp_MSscriptmvastable @artid int
  23183. as
  23184. declare @cmd          nvarchar(4000)
  23185. declare @dest_owner   nvarchar(255)
  23186. declare @dest_tabname sysname
  23187. declare @src_objid    int
  23188. declare @artcolumns   binary(32)
  23189. declare @schema_option binary(8)
  23190. declare @art_col      int
  23191. declare @this_col      int
  23192. declare @isset          int
  23193. declare @use_base_type tinyint
  23194.  
  23195. declare @spacer          nvarchar(1)
  23196. declare @nullability  nvarchar(10)
  23197. declare @typestring   nvarchar(255)
  23198. declare @col_name      sysname
  23199.  
  23200. -------- create temp table for command fragments
  23201.  
  23202. create table #proctext ( c1 int identity NOT NULL, procedure_text nvarchar(4000) collate database_default )
  23203.  
  23204. -------- get sysarticles information
  23205.  
  23206. select @dest_owner = dest_owner, @dest_tabname = dest_table, 
  23207.        @src_objid = objid, @artcolumns = columns, 
  23208.        @use_base_type = substring(schema_option,8,1) & 32
  23209. from sysarticles
  23210. where artid = @artid
  23211.  
  23212. if @dest_owner is not null
  23213. begin
  23214.     select @dest_owner = QUOTENAME( @dest_owner ) + N'.'
  23215. end
  23216. else
  23217. begin
  23218.     select @dest_owner = N''
  23219. end
  23220.  
  23221. -- script out CREATE TABLE statement
  23222.  
  23223. -- begin create table
  23224. select @cmd = N'create table ' + @dest_owner + QUOTENAME(@dest_tabname) + N'('
  23225. insert into #proctext(procedure_text) values( @cmd )
  23226.  
  23227. -- columns
  23228. select @art_col = 1
  23229. select @spacer = N' '
  23230.  
  23231. DECLARE hCColid CURSOR LOCAL FAST_FORWARD FOR 
  23232. select colid from syscolumns where id = @src_objid order by colid asc
  23233.  
  23234. OPEN hCColid
  23235.  
  23236. FETCH hCColid INTO @this_col
  23237.  
  23238. WHILE (@@fetch_status <> -1)
  23239. begin
  23240.    exec @isset = dbo.sp_isarticlecolbitset @this_col, @artcolumns
  23241.    select @col_name = name, 
  23242.           @nullability = case isnullable 
  23243.           when 0 then N'NOT NULL' 
  23244.           else N'NULL' end
  23245.           from syscolumns where id=@src_objid and @this_col=colid 
  23246.    if @isset != 0 and @col_name is not null
  23247.    begin
  23248.         if @use_base_type <> 0
  23249.         begin
  23250.             exec dbo.sp_gettypestring @src_objid, @this_col, @typestring OUTPUT
  23251.         end
  23252.         else
  23253.         begin
  23254.             exec dbo.sp_MSgettypestringudt @src_objid, @this_col, @typestring OUTPUT
  23255.         end
  23256.         select @cmd = @spacer + QUOTENAME(@col_name) + N' ' + @typestring + N' ' + @nullability 
  23257.         insert into #proctext(procedure_text) values( @cmd )
  23258.         select @art_col = @art_col + 1
  23259.         select @spacer = N','
  23260.    end
  23261.    FETCH hCColid INTO @this_col
  23262. end
  23263.  
  23264. CLOSE hCColid
  23265. DEALLOCATE hCColid
  23266.  
  23267. -- end create table
  23268. insert into #proctext(procedure_text) values( N')' )
  23269.  
  23270. select procedure_text from #proctext order by c1 asc
  23271. go
  23272. EXEC dbo.sp_MS_marksystemobject sp_MSscriptmvastable
  23273. GO
  23274.  
  23275. --------------------------------------------------------------------------
  23276. --------------------------------------------------------------------------
  23277.  
  23278. print ''
  23279. print 'Creating procedure sp_fetchshowcmdsinput'
  23280. go
  23281. SET ARITHABORT ON
  23282. SET NUMERIC_ROUNDABORT OFF
  23283. SET CONCAT_NULL_YIELDS_NULL ON
  23284. SET QUOTED_IDENTIFIER ON
  23285. SET ANSI_NULLS ON
  23286. SET ANSI_PADDING ON
  23287. SET ANSI_WARNINGS ON
  23288. go
  23289. create procedure sp_fetchshowcmdsinput @numcmds int
  23290. as
  23291. create table #rcmds( article_id int NOT NULL, partial_command int NOT NULL, command varbinary(1024) NULL, 
  23292. xactid binary(10) NOT NULL, xact_seqno binary(10) NOT NULL, publication_id int NOT NULL, 
  23293. command_id int NOT NULL, command_type int NOT NULL, originator_srvname nvarchar(128) collate database_default null, 
  23294. originator_db nvarchar(128) collate database_default null)
  23295. insert into #rcmds exec dbo.sp_replcmds @numcmds
  23296. 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
  23297. drop table #rcmds
  23298. go
  23299. SET ANSI_NULLS OFF
  23300. go
  23301. EXEC dbo.sp_MS_marksystemobject sp_fetchshowcmdsinput
  23302. GO
  23303.  
  23304. --------------------------------------------------------------------------
  23305. --------------------------------------------------------------------------
  23306.  
  23307. print ''
  23308. print 'Creating procedure sp_replshowcmds'
  23309. go
  23310.  
  23311. create procedure sp_replshowcmds @maxtrans int = 1
  23312. as
  23313. declare @query nvarchar(1024)
  23314. declare @dbname sysname
  23315. select @dbname = db_name()
  23316.  
  23317. select @query = 'execute dbo.sp_fetchshowcmdsinput ' + convert( nvarchar, @maxtrans )
  23318. execute master..xp_printstatements @query, @dbname
  23319. go
  23320.  
  23321. EXEC dbo.sp_MS_marksystemobject sp_replshowcmds
  23322. GO
  23323.  
  23324. print ''
  23325. print 'Creating procedure sp_article_validation'
  23326. go
  23327.  
  23328. create procedure sp_article_validation
  23329. @publication sysname,
  23330. @article sysname,
  23331. -- The following are values passed to the sp_table_validation call at the subscriber.
  23332. @rowcount_only smallint = 1,       
  23333. /* 
  23334. The @rowcount_only param is overloaded for shiloh release due to backward compatibility concerns.
  23335. In shiloh, the checksum functionality has changed.   So 7.0 subscribers will have the old checksum 
  23336. routines, which generate different CRC values, and do not have functionality for vertical partitions,
  23337. or logical table structures where column offsets differ (due to ALTER TABLEs that DROP and ADD columns).
  23338.  
  23339. In 7.0, this was a bit column.  0 meant do not do just a rowcount - do a checksum.  1 meant just do a 
  23340. rowcount.
  23341.  
  23342. For Shiloh, this parameter is changed to a smallint with these options:
  23343. 0 - Do a 7.0 compatible checksum
  23344. 1 - Do a rowcount check only
  23345. 2 - Use new Shiloh checksum functionality.  Note that because 7.0 subscribers will 
  23346. take this parameter as a bit type, not a smallint, it will be interpreted as simply
  23347. ON.  That means that passing a 2, and having a 7.0 subscriber, will result in the 7.0
  23348. subscriber doing only rowcount validation.   The Shiloh subscribers will do both
  23349. rowcount and checksum.  If you want 7.0 subscribers to do checksum validation, use 
  23350. the value of 0 for this parameter.   Shiloh subscribers can do the 7.0 compatible 
  23351. checksum, but that checksum has the same 7.0 limitations for vertical partitions 
  23352. and differences in physical table structure.)
  23353. */
  23354.               
  23355. @full_or_fast tinyint = 2,  -- full (value 0) does COUNT(*) 
  23356.                             -- fast (value 1) uses sysindexes.rows if table (not view); 
  23357.                             -- conditional fast (VALUE 2) , first tries fast method, but
  23358.                             -- reverts to full if fast method shows differences.
  23359. @shutdown_agent bit = 0,    -- If 1 will raise error 20578, which will signal subscriber synchronization agent to shutdown
  23360.                             -- immediately after successful validation
  23361. @subscription_level bit = 0        -- Whether or not the validation is only picked up by a set of subscribers
  23362.                                 -- that are specified by calls to sp_marksubscriptionvalidation.
  23363. , @reserved int = NULL            -- If not null, the sp is called from sp_publication_validation.
  23364. as
  23365.  
  23366. declare @publication_guid uniqueidentifier
  23367. declare @publication_id int
  23368. declare @article_guid uniqueidentifier
  23369. declare @article_id int
  23370. declare @source_name sysname
  23371. declare @source_owner sysname
  23372. declare @partition_view_id sysname, @table_id sysname
  23373. declare @sync_name sysname
  23374. declare @destination_table sysname
  23375. declare @destination_owner sysname
  23376. declare @columns varbinary(32) 
  23377. declare @command varchar (4096)
  23378. declare @retcode int
  23379. declare @actual_rowcount bigint
  23380. declare @actual_checksum numeric
  23381. declare @status int
  23382. declare @active int
  23383. declare @publish_bit int
  23384. declare @table_name sysname                    -- base table name var to passed to sp_table_validation
  23385.     , @allow_dts bit
  23386.     , @dts_part int
  23387.     
  23388. set nocount on
  23389.  
  23390.  
  23391. set @active = 1
  23392. set @publish_bit = 1
  23393. set @dts_part = 64
  23394.  
  23395. -- Check if the database is published for transactional
  23396. if not exists (select * from master..sysdatabases where name = db_name() collate database_default and (category & @publish_bit) = @publish_bit)
  23397. begin
  23398.     raiserror(20026, 16, -1, @publication)
  23399.     return 1
  23400. end
  23401.  
  23402. -- Get Publication Information
  23403. select @publication_id = pubid, @allow_dts = allow_dts from syspublications where name = @publication
  23404. if @publication_id is null
  23405. begin
  23406.     raiserror(20026, 16, -1, @publication)
  23407.     return 1
  23408. end
  23409.  
  23410. -- Get Article Information
  23411. select @article_id = artid, @sync_name = OBJECT_NAME(sync_objid),@partition_view_id=sync_objid,
  23412.     @destination_table = dest_table, @destination_owner = dest_owner, 
  23413.     @status = status, @table_name = OBJECT_NAME(objid),@table_id=objid,
  23414.     @columns = columns from sysarticles where name = @article and pubid=@publication_id
  23415.  
  23416. if @article_id is null
  23417. begin
  23418.     raiserror(20027, 16, -1, @article)
  23419.     return 1
  23420. end
  23421.  
  23422. -- Security check
  23423. -- Only people have 'select all' permission on the base table can do validation
  23424. if permissions(@table_id) & 1 <> 1
  23425. begin
  23426.     declare @qual_name nvarchar(512)
  23427.     exec dbo.sp_MSget_qualified_name @table_id, @qual_name output
  23428.     raiserror(20623, 16, -1, @article, @qual_name)
  23429.     return 1
  23430. end
  23431.  
  23432. -- Make sure article status is 'active' 
  23433. if (@status & @active) <> @active
  23434. begin
  23435.     -- Article is not active
  23436.     raiserror(20523, 16, -1, @article)
  23437.     return 1
  23438. end
  23439.  
  23440.  
  23441. if @allow_dts = 1
  23442. begin
  23443.     if @rowcount_only <> 1
  23444.     begin
  23445.         raiserror(20612, 16, -1)
  23446.         return (1) 
  23447.     end
  23448.     -- For dts horizontal partitioned article, no validation is possible, do nothing or
  23449.     -- raise error.
  23450.     if (@status & @dts_part <> 0)
  23451.     begin
  23452.         -- sp_article_validation is called directly, raise error and fail
  23453.         if @reserved is null
  23454.         begin
  23455.             raiserror(20613, 16, -1)
  23456.             return (1) 
  23457.         end
  23458.         -- sp_article_validation is called by sp_publication_validation, 
  23459.         -- raise warning and contiue.
  23460.         else
  23461.         begin
  23462.             raiserror(20613, 10, -1)
  23463.             return (0)
  23464.         end
  23465.     end
  23466. end
  23467.             
  23468.     
  23469.     
  23470.  
  23471. -- Check if table has vertical partition OR horizontal partition
  23472. if exists (select * from sysarticles a, syscolumns b
  23473.     where
  23474.     (
  23475.     -- horizontal partition    exists if filter column is not zero
  23476.     a.filter <> 0
  23477.     
  23478.     OR
  23479.     --vertical partition
  23480.      (CONVERT(bit, convert(binary(2), SUBSTRING(convert(nvarchar,a.columns), CONVERT(tinyint, 16 - FLOOR((colid-1)/16)), 1)) & POWER(2, ((colid-1)%16))) = 0
  23481.            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)
  23482.     )
  23483.            AND a.objid = b.id
  23484.            AND a.name = @article
  23485.            AND a.pubid = @publication_id)
  23486. begin
  23487.     set @source_name = @sync_name
  23488.     select @source_owner= user_name(uid) from sysobjects where id=@partition_view_id
  23489.  
  23490.     -- Partitions only support new shiloh checksum functionality or row count validation.
  23491.     -- If 7.0 compatible checksum was asked for (@rowcount_only=0), it will be changed to 
  23492.     -- override specified value, making it truly only check rowcounts.   If shiloh checksum 
  23493.     -- was asked for, thats ok (@rowcount_only=2), thats ok and no need to change it.
  23494.     if (@rowcount_only = 0)
  23495.         set @rowcount_only = 1
  23496. end
  23497.  
  23498. else
  23499.  
  23500. begin
  23501.       set @source_name = @table_name
  23502.     select @source_owner= user_name(uid) from sysobjects where id=@table_id
  23503.  
  23504. end
  23505.  
  23506.  
  23507. begin tran -- The table validation and posting to the log MUST happen with a transaction
  23508.  
  23509. -- Get publisher's rowcount and/or checksum for the article
  23510. if @rowcount_only = 1
  23511. begin
  23512.     exec @retcode = dbo.sp_table_validation @table = @source_name, @expected_rowcount = @actual_rowcount OUTPUT,
  23513.         @rowcount_only = 1, @owner=@source_owner, @full_or_fast = 0, @table_name = @table_name   -- always do full count at publisher
  23514.     if @retcode <> 0 or @@error <> 0 
  23515.     begin
  23516.         commit tran
  23517.         return 1
  23518.     end
  23519. end
  23520. else  -- get checksum
  23521. begin
  23522.     exec @retcode = dbo.sp_table_validation @table = @source_name, @expected_rowcount = @actual_rowcount OUTPUT,
  23523.         @expected_checksum = @actual_checksum OUTPUT, @rowcount_only = @rowcount_only, @owner=@source_owner,
  23524.         @full_or_fast = 0, @table_name = @table_name   -- always do full count at publisher
  23525.     if @retcode <> 0 or @@error <> 0 
  23526.     begin
  23527.         commit tran
  23528.         return 1
  23529.     end
  23530. end
  23531.  
  23532. -- Post sp_table_validation on behalf of the article and send to subscribers
  23533. if @rowcount_only = 1
  23534. begin
  23535.     select @command = 'exec dbo.sp_table_validation @table = ''' + @destination_table + ''', @expected_rowcount = ' +
  23536.         convert(varchar(10), @actual_rowcount) + ', @rowcount_only = 1' +
  23537.         ', @full_or_fast = ' + convert(varchar(10), @full_or_fast) +
  23538.         ', @shutdown_agent = ' + convert(varchar(10), @shutdown_agent)
  23539. end
  23540. else
  23541. begin
  23542.     select @command = 'exec dbo.sp_table_validation @table = ''' + @destination_table + ''', @expected_rowcount = ' +
  23543.         convert(varchar(10), @actual_rowcount) + ', @expected_checksum = ' + 
  23544.         convert(varchar(100), @actual_checksum) + ', @rowcount_only = ' + convert(varchar(5),@rowcount_only) +
  23545.         ', @full_or_fast = ' + convert(varchar(10), @full_or_fast) +
  23546.         ', @shutdown_agent = ' + convert(varchar(10), @shutdown_agent)
  23547. end 
  23548.  
  23549. -- Add owner param if destination owner is not NULL
  23550. if (@destination_owner IS NOT NULL)
  23551. begin
  23552.     select @command = @command +
  23553.     ', @owner = ''' + @destination_owner + ''''
  23554. end
  23555.  
  23556. declare @command_type int
  23557. if @subscription_level = 0
  23558.     select @command_type = 35 -- SQL Server Only command type
  23559. else
  23560.     select @command_type = 69 -- sub validation command
  23561.  
  23562. exec @retcode = dbo.sp_replpostcmd 
  23563.     0,              -- partial flag
  23564.     @publication_id, 
  23565.     @article_id, 
  23566.     @command_type,            -- SQL Server Only command type
  23567.     @command
  23568. if @retcode <> 0 or @@error <> 0
  23569. begin
  23570.     commit tran
  23571.     return 1
  23572. end
  23573.  
  23574. commit tran
  23575.  
  23576. Go
  23577.  
  23578. EXEC dbo.sp_MS_marksystemobject sp_article_validation
  23579.  
  23580. print ''
  23581. print 'Creating procedure sp_publication_validation'
  23582. go
  23583.  
  23584.  
  23585. create procedure sp_publication_validation
  23586. @publication sysname,
  23587. @rowcount_only smallint = 1,
  23588. /* 
  23589. The @rowcount_only param is overloaded for shiloh release due to backward compatibility concerns.
  23590. In shiloh, the checksum functionality has changed.   So 7.0 subscribers will have the old checksum 
  23591. routines, which generate different CRC values, and do not have functionality for vertical partitions,
  23592. or logical table structures where column offsets differ (due to ALTER TABLEs that DROP and ADD columns).
  23593.  
  23594. In 7.0, this was a bit column.  0 meant do not do just a rowcount - do a checksum.  1 meant just do a 
  23595. rowcount.
  23596.  
  23597. For Shiloh, this parameter is changed to a smallint with these options:
  23598. 0 - Do a 7.0 compatible checksum
  23599. 1 - Do a rowcount check only
  23600. 2 - Use new Shiloh checksum functionality.  Note that because 7.0 subscribers will 
  23601. take this parameter as a bit type, not a smallint, it will be interpreted as simply
  23602. ON.  That means that passing a 2, and having a 7.0 subscriber, will result in the 7.0
  23603. subscriber doing only rowcount validation.   The Shiloh subscribers will do both
  23604. rowcount and checksum.  If you want 7.0 subscribers to do checksum validation, use 
  23605. the value of 0 for this parameter.   Shiloh subscribers can do the 7.0 compatible 
  23606. checksum, but that checksum has the same 7.0 limitations for vertical partitions 
  23607. and differences in physical table structure.)
  23608. */
  23609.  
  23610. @full_or_fast tinyint = 2,  -- full (value 0) does COUNT(*) 
  23611.                             -- fast (value 1) uses sysindexes.rows if table (not view); 
  23612.                             -- conditional fast (VALUE 2) , first tries fast method, but
  23613.                             -- reverts to full if fast method shows differences.
  23614. @shutdown_agent bit = 0     -- Set for last article in publication, which will signal subscriber synchronization agent to shutdown
  23615.                             -- immediately after successful validation
  23616. as
  23617.  
  23618. set nocount on
  23619.  
  23620. declare @publication_id int
  23621. declare @article sysname
  23622. declare @article2 sysname
  23623. declare @retcode int
  23624. declare @publish_bit int
  23625.  
  23626.     
  23627. set @publish_bit = 1
  23628.  
  23629. -- Check if the database is published for transactional
  23630. if not exists (select * from master..sysdatabases where name = db_name() collate database_default and (category & @publish_bit) = @publish_bit)
  23631. begin
  23632.     raiserror(20026, 16, -1, @publication)
  23633.     return 1
  23634. end
  23635.  
  23636. -- Get Publication Information
  23637. select @publication_id = pubid from syspublications where name = @publication
  23638. if @publication_id is null
  23639. begin
  23640.     raiserror(20026, 16, -1, @publication)
  23641.     return 1
  23642. end
  23643.  
  23644. -- Security Check will be done inside sp_article_validation
  23645. -- Security check
  23646. -- Only people have 'select all' permission on the base table can do validation
  23647. declare @table_id int
  23648.  
  23649. select top 1 @article = name, @table_id = objid from sysarticles where
  23650.     pubid = @publication_id and 
  23651.     (status & 1) <> 0 and   -- active articles only
  23652.     (type & 1) <> 0 and        -- only checksum tables/views.
  23653.     ((permissions(objid) & 1) <> 1)
  23654.  
  23655. if @table_id is not null
  23656. begin
  23657.     declare @qual_name nvarchar(512)
  23658.     exec dbo.sp_MSget_qualified_name @table_id, @qual_name output
  23659.     raiserror(20623, 16, -1, @article, @qual_name)
  23660.     return 1
  23661. end
  23662.  
  23663. declare hC CURSOR LOCAL FAST_FORWARD for select name from sysarticles where pubid = @publication_id and
  23664. (status & 1) <> 0 and   -- active articles only
  23665. (type & 1) <> 0            -- only checksum tables/views.
  23666.  
  23667. open hC
  23668. fetch hC into @article
  23669. while (@@fetch_status <> -1)
  23670. begin
  23671.     set @article2 = @article
  23672.  
  23673.     -- Look ahead to next article
  23674.     fetch hC into @article
  23675.  
  23676.     -- If we are at the last article, pass the @shutdown_agent value
  23677.     if (@@fetch_status = -1) 
  23678.     begin
  23679.         exec @retcode = dbo.sp_article_validation @publication, @article2, @rowcount_only = @rowcount_only,
  23680.             @full_or_fast = @full_or_fast, @shutdown_agent = @shutdown_agent, @reserved = 1
  23681.  
  23682.     end
  23683.     else
  23684.         exec @retcode = dbo.sp_article_validation @publication, @article2, @rowcount_only = @rowcount_only,
  23685.             @full_or_fast = @full_or_fast, @reserved = 1
  23686.     
  23687.     if @retcode <> 0 or @@error <> 0
  23688.     begin
  23689.         close hC
  23690.         deallocate hC
  23691.         return 1
  23692.     end
  23693. end
  23694. close hC
  23695. deallocate hC
  23696. go
  23697.  
  23698. EXEC dbo.sp_MS_marksystemobject sp_publication_validation
  23699. GO
  23700.  
  23701.  
  23702. print ''
  23703. print 'Creating procedure sp_marksubscriptionvalidation'
  23704. go
  23705.  
  23706.  
  23707. CREATE PROCEDURE sp_marksubscriptionvalidation (
  23708.     @publication sysname,    /* publication name */
  23709.     @subscriber sysname,             /* subscriber name */
  23710.     @destination_db sysname   /* destination database name */
  23711. ) AS
  23712.  
  23713.     DECLARE @retcode int, @pubid int
  23714.  
  23715.     DECLARE @artid int, @active tinyint
  23716.     DECLARE @srvid smallint
  23717.     DECLARE @non_sql_flag bit
  23718.  
  23719.   
  23720.     -- Initialization
  23721.     select @active = 2
  23722.  
  23723.     /* 
  23724.     ** Security Check.
  23725.     */
  23726.     exec @retcode = dbo.sp_MSreplcheck_publish
  23727.     if @@ERROR <> 0 or @retcode <> 0
  23728.         return(1)
  23729.  
  23730.     /* Validate names */
  23731.  
  23732.     EXECUTE @retcode = dbo.sp_validname @publication
  23733.     IF @@ERROR <> 0 OR @retcode <> 0
  23734.         RETURN (1)
  23735.  
  23736.     EXECUTE @retcode = dbo.sp_validname @subscriber
  23737.     IF @@ERROR <> 0 OR @retcode <> 0
  23738.         RETURN (1)
  23739.  
  23740.     EXECUTE @retcode = dbo.sp_validname @destination_db
  23741.     IF @@ERROR <> 0 OR @retcode <> 0
  23742.         RETURN (1)
  23743.  
  23744.     /*
  23745.     ** Parameter Check:  @publication
  23746.     ** Check to make sure that the publication exists, that it's not NULL,
  23747.     ** and that it conforms to the rules for identifiers.
  23748.     */
  23749.     SELECT @pubid = pubid FROM syspublications WHERE name = @publication
  23750.     if @pubid is null
  23751.     begin
  23752.         RAISERROR (20026, 16, -1, @publication)
  23753.         RETURN (1)
  23754.     END
  23755.  
  23756.     /*
  23757.     ** Parameter Check:  @subscriber
  23758.     ** Check to make sure that the subscriber exists
  23759.     */
  23760.     select @subscriber = UPPER(@subscriber)
  23761.         
  23762.     SELECT @srvid = srvid, @non_sql_flag = 
  23763.         case when srvproduct = N'MSREPL-NONSQL' then 1
  23764.         else 0 end
  23765.         FROM master..sysservers
  23766.         WHERE UPPER(srvname) = UPPER(@subscriber) collate database_default
  23767.           AND (srvstatus & 4) <> 0
  23768.     if @srvid is null
  23769.     BEGIN
  23770.         RAISERROR (14063, 16, -1)
  23771.         RETURN (1)
  23772.     END
  23773.  
  23774.     if @non_sql_flag = 1
  23775.     begin
  23776.         RAISERROR (20614, 16, -1)
  23777.         RETURN (1)
  23778.     end
  23779.  
  23780.     -- Wrong dest_db will be caught by the following query
  23781.  
  23782.     -- Check to make sure the subscription exists 
  23783.     IF NOT EXISTS (SELECT *
  23784.           FROM syssubscriptions sub,
  23785.                sysextendedarticlesview art,
  23786.                syspublications pub
  23787.          WHERE pub.pubid = @pubid
  23788.            AND sub.srvid = @srvid
  23789.            AND sub.artid = art.artid
  23790.            AND art.pubid = pub.pubid
  23791.            AND sub.dest_db = @destination_db)
  23792.     BEGIN
  23793.         RAISERROR (14055, 16, -1)
  23794.         RETURN (1)
  23795.     END
  23796.  
  23797.     -- Select an article for that is actively subscribed.
  23798.     -- If none is found, do nothing
  23799.     select top 1 @artid = art.artid 
  23800.           FROM syssubscriptions sub,
  23801.                sysextendedarticlesview art
  23802.          WHERE sub.srvid = @srvid
  23803.            AND sub.artid = art.artid
  23804.            AND art.pubid = @pubid
  23805.            AND sub.dest_db = @destination_db
  23806.            AND sub.status = @active
  23807.  
  23808.     if @artid is null
  23809.         return 0
  23810.  
  23811.     declare @command nvarchar (1000)
  23812.  
  23813.     -- No need to quote them
  23814.     select @command = @subscriber + @destination_db
  23815.     exec @retcode = dbo.sp_replpostcmd 
  23816.         0,              -- partial flag
  23817.         @pubid, 
  23818.         @artid, 
  23819.         68,             -- subscription validation marker
  23820.         @command
  23821.     if @retcode <> 0 or @@error <> 0
  23822.         return 1
  23823.  
  23824.     RETURN(0)
  23825. go
  23826.  
  23827. EXEC dbo.sp_MS_marksystemobject sp_marksubscriptionvalidation
  23828. GO
  23829.  
  23830. print ''
  23831. print 'Creating procedure sp_dropanonymousagent'
  23832. go
  23833.  
  23834.  
  23835. CREATE PROCEDURE sp_dropanonymousagent
  23836. @subid uniqueidentifier,
  23837. @type int -- 1 tran sub, 2 merge sub
  23838. as
  23839.     set nocount on 
  23840.     declare @login sysname
  23841.     -- Null @login indicates sysadmin or db_owner
  23842.     if IS_SRVROLEMEMBER ('sysadmin') = 0 and is_member('db_owner') = 0
  23843.         select @login = suser_sname()
  23844.     /*
  23845.     ** Get distribution server information for remote RPC
  23846.     ** agent verification.
  23847.     */
  23848.     declare @distributor sysname
  23849.     declare @distribdb sysname
  23850.     declare @distproc nvarchar(1000)
  23851.     declare @retcode int
  23852.  
  23853.     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  23854.         @distribdb = @distribdb OUTPUT
  23855.  
  23856.     IF @@error <> 0 OR @retcode <> 0
  23857.     BEGIN
  23858.         RAISERROR (14071, 16, -1)
  23859.         RETURN (1)
  23860.     END
  23861.  
  23862.     /*
  23863.     ** Call proc to change the distributor
  23864.     */
  23865.     SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  23866.         '.dbo.sp_MSdrop_anonymous_entry'
  23867.  
  23868.     exec @retcode = @distproc 
  23869.         @subid = @subid,
  23870.         @login = @login,
  23871.         @type = @type
  23872.  
  23873.     IF @@error <> 0 OR @retcode <> 0
  23874.         RETURN (1)
  23875.  
  23876.     RETURN (0)
  23877. go
  23878.  
  23879. EXEC dbo.sp_MS_marksystemobject sp_dropanonymousagent
  23880. GO
  23881.  
  23882. print ''
  23883. print 'Creating procedure sp_replrestart'
  23884. go
  23885.  
  23886.  
  23887. CREATE PROCEDURE sp_replrestart 
  23888. AS
  23889.  
  23890.     SET NOCOUNT ON
  23891.  
  23892.     /*
  23893.     ** Declarations.
  23894.     */
  23895.     declare @retcode int
  23896.         ,@lsn binary(10)
  23897.         ,@dist_lsn binary(10)
  23898.         ,@distributor sysname
  23899.         ,@distribdb sysname
  23900.         ,@distproc nvarchar(4000)
  23901.         ,@dbname sysname
  23902.     /*
  23903.     ** Initializations
  23904.     */
  23905.     select @retcode = 0
  23906.     select @dbname = db_name()
  23907.  
  23908.     /*
  23909.     ** Security
  23910.     */
  23911.     exec @retcode = dbo.sp_MSreplcheck_publish
  23912.     if @@ERROR <> 0 or @retcode <> 0
  23913.         return(1)
  23914.  
  23915.     -- Make sure the database is published.
  23916.     IF (SELECT category & 1
  23917.           FROM master..sysdatabases
  23918.          WHERE name = @dbname collate database_default) = 0
  23919.     BEGIN
  23920.         RAISERROR (14013, 16, -1)
  23921.         RETURN (1)
  23922.     END
  23923.  
  23924.     -- Make sure that the log reader is not running
  23925.     -- Use 0 so that it will not hold the repl proc structure (the lock).
  23926.     exec @retcode = dbo.sp_replcmds 0
  23927.     if @@ERROR <> 0 or @retcode <> 0
  23928.     begin
  23929.         RAISERROR (20610, 16, -1, 'sp_replrestart')
  23930.         return(1)
  23931.     end
  23932.  
  23933.     /*
  23934.     ** Get distribution server information for remote RPC call.
  23935.     */
  23936.  
  23937.     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  23938.                                        @distribdb = @distribdb OUTPUT
  23939.  
  23940.     IF @@ERROR <> 0 OR  @retcode <> 0
  23941.     BEGIN
  23942.         RAISERROR (14071, 16, -1)
  23943.         RETURN (1)
  23944.     END
  23945.  
  23946.     -- Get max dist lsn
  23947.     SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + '.dbo.sp_MSget_last_transaction'
  23948.     EXECUTE @retcode = @distproc 
  23949.         @publisher = @@SERVERNAME,
  23950.         @publisher_db = @dbname,
  23951.         @max_xact_seqno = @dist_lsn output
  23952.     IF @@ERROR <> 0 or @retcode <> 0
  23953.         return -1
  23954.  
  23955.     if @dist_lsn is null
  23956.         set @dist_lsn = 0x0
  23957.  
  23958.     -- To safeguard the case when the logreader is started after the check later
  23959.     -- use a tran to prevent the logreader from picking up the new lsns
  23960.     begin tran
  23961.  
  23962.     while 1 = 1
  23963.     begin
  23964.         -- Get publisher's lsn
  23965.         EXEC @retcode = dbo.sp_replincrementlsn @lsn OUTPUT
  23966.         IF @@ERROR <> 0 or @retcode <> 0
  23967.             goto UNDO
  23968.  
  23969.         if @lsn > @dist_lsn
  23970.             break
  23971.     end
  23972.  
  23973.     /* Mark the new starting point of the replication.*/
  23974.     exec @retcode = dbo.sp_repldone NULL, NULL, 0, 0, 1
  23975.     IF @@ERROR <> 0 or @retcode <> 0
  23976.         GOTO UNDO
  23977.  
  23978.     /* release our hold on the db as logreader */
  23979.     EXEC @retcode = dbo.sp_replflush
  23980.     IF @@ERROR <> 0 or @retcode <> 0
  23981.         GOTO UNDO
  23982.  
  23983.     commit tran
  23984.     return 0
  23985.  
  23986. UNDO:
  23987.     if @@trancount <> 0
  23988.         rollback tran
  23989. go
  23990.  
  23991. EXEC dbo.sp_MS_marksystemobject sp_replrestart
  23992. GO
  23993.  
  23994.  
  23995. print ''
  23996. print 'Creating procedure sp_MSpub_adjust_identity'
  23997. go
  23998.  
  23999. CREATE PROCEDURE sp_MSpub_adjust_identity
  24000. @artid int = null
  24001. as
  24002.     set nocount on
  24003.  
  24004.     declare @retcode int
  24005.     declare @cmd nvarchar(1000)
  24006.     declare @objid int, @threshhold int
  24007.     declare @pub_range bigint, @next_seed bigint, @current_pub_range bigint
  24008.     declare    @last_seed bigint, @identity_so_far bigint, @threshold int, @range bigint
  24009.     declare @database sysname, @table_name sysname
  24010.     declare @qualname nvarchar(512)
  24011.     DECLARE @distributor sysname
  24012.     DECLARE @distribdb sysname
  24013.  
  24014.     /*
  24015.     ** Security Check.
  24016.     */
  24017.     exec @retcode = dbo.sp_MSreplcheck_publish
  24018.     if @@ERROR <> 0 or @retcode <> 0
  24019.         return(1)
  24020.     
  24021.     select @database = db_name()
  24022.  
  24023.     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  24024.                                        @distribdb = @distribdb OUTPUT
  24025.     IF @@ERROR <> 0
  24026.     BEGIN
  24027.         RAISERROR (14071, 16, -1)
  24028.         RETURN (1)
  24029.     END
  24030.  
  24031.     DECLARE adjust_identity CURSOR LOCAL FAST_FORWARD FOR
  24032.         SELECT art1.objid
  24033.           FROM sysarticles art1,
  24034.                sysarticleupdates art2
  24035.           where art1.artid = art2.artid and
  24036.                 art2.identity_support = 1 and
  24037.                 (art1.artid = @artid or @artid is null)
  24038.     FOR READ ONLY
  24039.  
  24040.     OPEN adjust_identity        
  24041.     FETCH adjust_identity INTO @objid
  24042.     WHILE (@@fetch_status <> -1)
  24043.     begin
  24044.         select @table_name = object_name(@objid)
  24045.         exec @retcode = dbo.sp_MSget_qualified_name @objid, @qualname OUTPUT
  24046.         
  24047.         select @range = range, @pub_range = pub_range, @current_pub_range = current_pub_range, 
  24048.             @last_seed = last_seed, 
  24049.             @threshold = threshold from 
  24050.             MSpub_identity_range where objid=@objid
  24051.   
  24052.         select @identity_so_far = ident_current(@qualname)
  24053.  
  24054.         if @last_seed is null
  24055.         begin
  24056.             -- First time
  24057.             select @last_seed = (@identity_so_far / @pub_range) * @pub_range
  24058.             -- We always reserve a new range for the publisher without reseeding 
  24059.             -- the publisher, and we guarantee to have more slots then 
  24060.             -- a full range initially for the publisher.
  24061.             if    (@pub_range > 0 and @last_seed < @identity_so_far) or
  24062.                 (@pub_range < 0 and @last_seed > @identity_so_far)
  24063.                 select @last_seed = @last_seed + @pub_range
  24064.  
  24065.             select @next_seed = @last_seed + @pub_range
  24066.             -- Initialize distribution side entry
  24067.             SELECT @cmd = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSinsert_identity'
  24068.             EXEC @retcode = @cmd
  24069.                 @publisher = @@servername,
  24070.                 @publisher_db = @database,
  24071.                 @tablename = @table_name,
  24072.                 @identity_support = 1,
  24073.                 @pub_identity_range = 0, -- We don't need this at the distributor
  24074.                 @identity_range = @range,
  24075.                 @threshold     = @threshold,
  24076.                 -- Make sure we don't have gap at the beginning
  24077.                 @next_seed    = @next_seed,
  24078.                 @max_identity = null
  24079.             IF @@ERROR <> 0 OR @retcode <> 0
  24080.                 GOTO UNDO
  24081.             -- Add constraint only without reseeding.
  24082.             exec @retcode = dbo.sp_MSreseed
  24083.                 @objid = @objid,
  24084.                 @next_seed = @last_seed,
  24085.                 @range = @pub_range,
  24086.                 @is_publisher = -1,
  24087.                 @check_only = 1,
  24088.                 @initial_setting = 1,
  24089.                 @bound_value = @identity_so_far
  24090.  
  24091.             IF @@ERROR <> 0 OR @retcode <> 0
  24092.                 GOTO UNDO
  24093.             update MSpub_identity_range set last_seed = @last_seed where objid = @objid
  24094.             IF @@ERROR <> 0
  24095.                 GOTO UNDO
  24096.         end
  24097.         else
  24098.         begin
  24099.  
  24100.             -- Leave one slot unused. This is to prevent violation of primary key constraint
  24101.             -- if the next value is used by a subscriber and the publisher has received it.
  24102.             -- It seems the pk constraint will be validated before this check.
  24103.             declare @actual_range int
  24104.             if @current_pub_range > 0
  24105.                 select @actual_range = @current_pub_range -1
  24106.             else
  24107.                 select @actual_range = @current_pub_range +1
  24108.  
  24109.             -- Calculate the current ratio
  24110.             if 100*(@identity_so_far - @last_seed)/@actual_range >= @threshold
  24111.             -- need bump up
  24112.             begin
  24113.                 SELECT @cmd = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSfetchAdjustidentityrange'
  24114.                 EXEC @retcode = @cmd
  24115.                     @publisher = @@servername,
  24116.                     @publisher_db = @database,
  24117.                     @tablename = @table_name,
  24118.                     @adjust_only = 1,
  24119.                     @for_publisher = 1,
  24120.                     @range = @pub_range,
  24121.                     @next_seed = @next_seed output
  24122.                 IF @@ERROR <> 0 OR @retcode <> 0
  24123.                     GOTO UNDO
  24124.  
  24125.                 select @last_seed = @next_seed - @pub_range
  24126.                 
  24127.                 update MSpub_identity_range set last_seed = @last_seed,
  24128.                     current_pub_range = @pub_range
  24129.                     where objid = @objid
  24130.                 IF @@ERROR <> 0
  24131.                     GOTO UNDO
  24132.                 -- RESEED and change constraint
  24133.                 exec @retcode = dbo.sp_MSreseed
  24134.                     @objid = @objid,
  24135.                     @next_seed = @last_seed,
  24136.                     @range = @pub_range,
  24137.                     @is_publisher = -1
  24138.                 IF @@ERROR <> 0 OR @retcode <> 0
  24139.                     GOTO UNDO
  24140.             end
  24141.         end
  24142.  
  24143.         FETCH adjust_identity INTO @objid
  24144.     end
  24145.     return 0
  24146. UNDO:
  24147.     -- No need to start a transaction.
  24148.     return 1
  24149. go
  24150.  
  24151. EXEC dbo.sp_MS_marksystemobject sp_MSpub_adjust_identity
  24152. GO
  24153.  
  24154.  
  24155. print ''
  24156. print 'Creating procedure sp_helparticledts'
  24157. go
  24158.  
  24159. CREATE PROCEDURE sp_helparticledts (
  24160.     @publication sysname,        /* Publication name */
  24161.     @article sysname             /* Article name */
  24162.     ) AS
  24163.  
  24164.     SET NOCOUNT ON
  24165.  
  24166.     /*
  24167.     ** Declarations.
  24168.     */
  24169.  
  24170.     DECLARE @artid int
  24171.     DECLARE @pubid int
  24172.     DECLARE @retcode int
  24173.     declare @article_name sysname
  24174.  
  24175.    /*
  24176.     ** Check to see if the database has been activated for publication.
  24177.     */
  24178.  
  24179.     IF (SELECT category & 1
  24180.           FROM master..sysdatabases
  24181.          WHERE name = DB_NAME() collate database_default) = 0
  24182.  
  24183.     BEGIN
  24184.             RAISERROR (14013, 16, -1)
  24185.             RETURN (1)
  24186.     END
  24187.  
  24188.  
  24189.     /*
  24190.     ** Parameter Check:  @publication.
  24191.     ** Make sure that the publication exists.
  24192.     */
  24193.  
  24194.     IF @publication IS NULL
  24195.         BEGIN
  24196.             RAISERROR (14043, 16, -1, '@publication')
  24197.             RETURN (1)
  24198.         END
  24199.  
  24200.     EXECUTE @retcode = dbo.sp_validname @publication
  24201.  
  24202.     IF @@ERROR <> 0 OR @retcode <> 0
  24203.     RETURN (1)
  24204.  
  24205.     declare @allow_dts bit
  24206.  
  24207.     SELECT @pubid = pubid, @allow_dts = allow_dts    
  24208.         FROM syspublications WHERE name = @publication
  24209.  
  24210.     IF @pubid IS NULL
  24211.         BEGIN
  24212.             RAISERROR (20026, 11, -1, @publication)
  24213.             RETURN (1)
  24214.         END
  24215.  
  24216.  
  24217.     if @allow_dts = 0
  24218.     begin
  24219.         RAISERROR ('The publication ''%s'' does not allow DTS.', 11, -1, @publication)
  24220.         RETURN (1)
  24221.     end
  24222.  
  24223.     /*
  24224.     ** Check to see that the article exists in sysarticles.
  24225.     ** Fetch the article identification number.
  24226.     */
  24227.  
  24228.     IF @article IS NULL
  24229.         BEGIN
  24230.             RAISERROR (14043, 16, -1, '@article')
  24231.             RETURN (1)
  24232.         END
  24233.  
  24234.     /*
  24235.     EXECUTE @retcode = dbo.sp_validname @article
  24236.  
  24237.     IF @retcode <> 0
  24238.     RETURN (1)
  24239.     */
  24240.  
  24241.     SELECT @artid = artid, @article_name = name
  24242.       FROM sysarticles
  24243.      WHERE name = @article
  24244.        AND pubid = @pubid
  24245.     IF @artid IS NULL
  24246.         BEGIN
  24247.             RAISERROR (20027, 11, -1, @article)
  24248.             RETURN (1)
  24249.         END
  24250.     
  24251.     select 
  24252.         N'pre_script_ignore_error_task_name' = @article_name + N'_pre_ignore_error',
  24253.         N'pre_script_task_name' = @article_name + N'_pre',
  24254.         N'transformation_task_name' = @article_name,
  24255.         N'post_script_ignore_error_task_name' = @article_name + N'_post_ignore_error',
  24256.         N'post_script_task_name' = @article_name + N'_post'
  24257. go
  24258.  
  24259. EXEC dbo.sp_MS_marksystemobject sp_helparticledts
  24260. GO
  24261.  
  24262.  
  24263. print ''
  24264. print 'Creating procedure sp_changesubscriptiondtsinfo'
  24265. go
  24266.  
  24267. CREATE PROCEDURE sp_changesubscriptiondtsinfo (
  24268.     @job_id varbinary(16),
  24269.     @dts_package_name sysname = NULL,
  24270.     @dts_package_password sysname = NULL,
  24271.     @dts_package_location nvarchar(12) = NULL
  24272.  
  24273.     ) AS
  24274.  
  24275.     /*
  24276.     ** Declarations.
  24277.     */
  24278.  
  24279.     DECLARE @srvid smallint
  24280.     DECLARE @artid int
  24281.     DECLARE @retcode int
  24282.     declare @login_name sysname
  24283.     declare @update_mode int
  24284.     declare @subscription_type int
  24285.     declare @dts_package_location_id int
  24286.  
  24287.     /*
  24288.     ** Initializations.
  24289.     */
  24290.     SET NOCOUNT ON
  24291.     
  24292.     
  24293.     /* 
  24294.     ** Get subscription properties and do Security Check.
  24295.     ** We use login_name stored in syssubscriptions to manage security 
  24296.     */
  24297.  
  24298.     select @update_mode = update_mode, @login_name = login_name,
  24299.         @subscription_type = subscription_type,
  24300.         @artid = artid              
  24301.         FROM syssubscriptions s WHERE 
  24302.             s.distribution_jobid = @job_id
  24303.  
  24304.     /*
  24305.     ** Check if the subscription exists.
  24306.     */
  24307.     IF @update_mode is null
  24308.     BEGIN
  24309.         RAISERROR (14055, 11, -1)
  24310.         RETURN (1)
  24311.     END
  24312.  
  24313.     if    @update_mode != 0
  24314.     begin
  24315.         RAISERROR(21180, 16, -1)    
  24316.         RETURN (1)
  24317.     end
  24318.  
  24319.     -- Only push store DTS info at distributor.
  24320.     if @subscription_type <> 0
  24321.     begin
  24322.         RAISERROR(21181, 16, -1)    
  24323.         RETURN (1)
  24324.     end
  24325.  
  24326.     --Security check
  24327.  
  24328.     IF  suser_sname(suser_sid()) <> @login_name AND is_srvrolemember('sysadmin') <> 1  
  24329.         AND is_member ('db_owner') <> 1
  24330.     BEGIN
  24331.         -- Only members of the sysadmin fixed server role, db_owner fixed database role or the creator of the subscription can change this subscription property.'
  24332.         RAISERROR(21175, 11, -1)
  24333.         RETURN (1)
  24334.     END
  24335.  
  24336.     -- Get pubid
  24337.     declare @pubid int
  24338.     select @pubid = pubid from sysarticles where artid = @artid
  24339.  
  24340.     /* Get subscription type of the publication */
  24341.     if not exists (select * from syspublications where
  24342.         pubid = @pubid and
  24343.         allow_dts = 1)
  24344.     begin
  24345.         RAISERROR(21178, 16, -1)    
  24346.         RETURN (1)
  24347.     end
  24348.  
  24349.     if @dts_package_location is null
  24350.         select @dts_package_location_id = null
  24351.     else IF LOWER(@dts_package_location) = N'distributor' 
  24352.         select @dts_package_location_id = 0
  24353.     ELSE IF LOWER(@dts_package_location) = N'subscriber' 
  24354.         select @dts_package_location_id = 1
  24355.     ELSE 
  24356.     begin
  24357.         raiserror(20587, 16, -1, '@dts_package_location', 'sp_changesubscriptiondtsinfo')
  24358.         return(1)
  24359.     end
  24360.  
  24361.     -- Encrypt DTS package password
  24362.     declare @change_password bit
  24363.  
  24364.     if @dts_package_password is null
  24365.         select @change_password = 0
  24366.     else
  24367.         select @change_password = 1
  24368.  
  24369.     -- When user sends in empty string, reset it to null.
  24370.     -- Have to do this before scramble because the result may contains invalid
  24371.     -- unicode code points which are equael to some collation.
  24372.     if @dts_package_password = N''
  24373.         select @dts_package_password = NULL
  24374.  
  24375.     declare @enc_dts_package_password nvarchar(524)
  24376.         select @enc_dts_package_password = @dts_package_password
  24377.  
  24378.     if @enc_dts_package_password is not null
  24379.     begin
  24380.         EXEC @retcode = master.dbo.xp_repl_encrypt @enc_dts_package_password OUTPUT
  24381.         IF @@error <> 0 OR @retcode <> 0
  24382.             return 1
  24383.     end
  24384.  
  24385.     /*
  24386.     ** Get distribution server information for remote RPC
  24387.     ** agent verification.
  24388.     */
  24389.     declare @distributor sysname
  24390.     declare @distribdb sysname
  24391.     declare @distproc nvarchar(1000)
  24392.  
  24393.     EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  24394.         @distribdb = @distribdb OUTPUT
  24395.  
  24396.     IF @@error <> 0 OR @retcode <> 0
  24397.     BEGIN
  24398.         RAISERROR (14071, 16, -1)
  24399.         RETURN (1)
  24400.     END
  24401.  
  24402.     /*
  24403.     ** Call proc to change the distributor
  24404.     */
  24405.     SELECT @distproc = RTRIM(@distributor) + '.' + @distribdb + 
  24406.         '.dbo.sp_MSchange_subscription_dts_info'
  24407.  
  24408.     exec @retcode = @distproc 
  24409.         @job_id = @job_id,
  24410.         @dts_package_name = @dts_package_name,
  24411.         @dts_package_password = @enc_dts_package_password,
  24412.         @dts_package_location = @dts_package_location_id,
  24413.         @change_password = @change_password
  24414.  
  24415.     IF @@error <> 0 OR @retcode <> 0
  24416.         RETURN (1)
  24417.  
  24418.     RETURN (0)
  24419. go
  24420.  
  24421. EXEC dbo.sp_MS_marksystemobject sp_changesubscriptiondtsinfo
  24422. GO
  24423.  
  24424. print ''
  24425. print 'Creating procedure sp_MSdrop_6x_replication_agent'
  24426. go
  24427. create procedure sp_MSdrop_6x_replication_agent
  24428. @job_id UNIQUEIDENTIFIER,
  24429. @category_id int
  24430. as
  24431.     declare @distbit int
  24432.     declare @db_name sysname
  24433.     declare @cmd varchar(4000)
  24434.  
  24435.     select @distbit = 16
  24436.  
  24437.     declare hCdatabase CURSOR LOCAL FAST_FORWARD FOR
  24438.         select name from master.dbo.sysdatabases 
  24439.             where
  24440.             category & @distbit <> 0 
  24441.         for read only
  24442.  
  24443.     open hCdatabase
  24444.     fetch next from hCdatabase into @db_name
  24445.     while (@@fetch_status <> -1)
  24446.     begin
  24447.  
  24448.         if @category_id = 13
  24449.         begin
  24450.             select @cmd = 'delete from ' + @db_name + '.dbo.MSlogreader_agents where job_id = convert (uniqueidentifier, ''' +
  24451.                 convert (varchar(100), @job_id) + ''')'
  24452.             exec (@cmd)
  24453.         end
  24454.         else if @category_id = 15   
  24455.         begin
  24456.             select @cmd = @db_name + '.dbo.sp_MSdrop_6x_publication'
  24457.             exec @cmd @job_id = @job_id
  24458.         end
  24459.         else
  24460.             return 0
  24461.  
  24462.         if @@ERROR <> 0
  24463.             return 1
  24464.         
  24465.         fetch next from hCdatabase into @db_name
  24466.     end
  24467.     close hCdatabase
  24468.     deallocate hCdatabase
  24469. go
  24470.  
  24471. EXEC dbo.sp_MS_marksystemobject sp_MSdrop_6x_replication_agent
  24472. GO
  24473.  
  24474. print ''
  24475. print 'Creating procedure sp_MSreinit_article'
  24476. go
  24477. create procedure sp_MSreinit_article (
  24478.     @publication sysname
  24479.     ,@article sysname = N'%'
  24480.     ,@need_new_snapshot bit = 0
  24481.     ,@need_reinit_subscription bit = 0
  24482.     ,@force_invalidate_snapshot bit    = 0
  24483.     ,@force_reinit_subscription bit = 0
  24484.     ,@check_only bit = 0
  24485. )
  24486. as
  24487.     declare @retcode int
  24488.         ,@active tinyint
  24489.         ,@subscribed tinyint
  24490.         ,@artid int
  24491.         ,@pubid int
  24492.         ,@none tinyint
  24493.         ,@immediate_sync_ready bit
  24494.         ,@allow_anonymous bit
  24495.  
  24496.     -- Initialization
  24497.     select @active = 2
  24498.     select @subscribed = 1
  24499.     SELECT @none = 2            /* Const: synchronization type 'none' */
  24500.     select @active = 2
  24501.     select @pubid = pubid, @immediate_sync_ready = immediate_sync_ready,
  24502.         @allow_anonymous = allow_anonymous 
  24503.         from syspublications where name = @publication
  24504.     
  24505.     if @article = N'%'
  24506.         select @artid = 0
  24507.     else
  24508.         select @artid = artid from sysarticles where name = @article and pubid = @pubid
  24509.  
  24510.     begin tran 
  24511.     save tran sp_MSreinit_article
  24512.  
  24513.     if @need_new_snapshot = 1 and @immediate_sync_ready = 1
  24514.     begin
  24515.         -- If at publication level, we know that we should do it since 
  24516.         -- @immediate_sync_ready = 1
  24517.         -- If at article level, we only do it for the articles that have been
  24518.         -- processed by the snapshot agent, but not new articles.
  24519.         -- sp_addarticle calls this proc at publication level.
  24520.         -- It also make calls to sp_articlecolumn and sp_articleview which in turn
  24521.         -- call this sp. We don't want to do anything here with those calls.
  24522.         if @artid = 0 or exists (select * from syssubscriptions s where 
  24523.             s.srvid < 0 and
  24524.             s.status = @active and
  24525.             s.artid = @artid)
  24526.         begin
  24527.             -- Fail and raiserror error
  24528.             if @force_invalidate_snapshot = 0
  24529.             begin
  24530.                 raiserror(20607, 16, -1)
  24531.                 goto UNDO
  24532.             end
  24533.  
  24534.             if @check_only = 0
  24535.             begin
  24536.                 UPDATE syspublications SET immediate_sync_ready = 0 WHERE 
  24537.                     pubid = @pubid and
  24538.                     immediate_sync_ready <> 0
  24539.                 IF @@ERROR <> 0
  24540.                     goto UNDO
  24541.  
  24542.                 DECLARE @distributor sysname
  24543.                     , @distribdb sysname
  24544.                     , @distproc nvarchar (255)
  24545.                     , @dbname sysname
  24546.  
  24547.                 select @dbname = db_name()
  24548.  
  24549.                 EXEC @retcode = dbo.sp_helpdistributor @rpcsrvname = @distributor OUTPUT,
  24550.                                                    @distribdb = @distribdb OUTPUT
  24551.                 IF @retcode <> 0 OR @@ERROR <> 0
  24552.                     goto UNDO
  24553.  
  24554.                 IF @distribdb IS NULL OR @distributor IS NULL
  24555.                 BEGIN
  24556.                     RAISERROR (14071, 16, -1)
  24557.                     goto UNDO
  24558.                 END
  24559.  
  24560.                 -- Deactivate virtual (but not virtual anonymous) subscriptions at the distributor
  24561.                 SELECT @distproc = RTRIM(@distributor) + '.' + RTRIM(@distribdb) + '.dbo.sp_MSinvalidate_snapshot'
  24562.                 EXEC @retcode = @distproc 
  24563.                     @publisher = @@SERVERNAME, 
  24564.                     @publisher_db = @dbname, 
  24565.                     @publication = @publication
  24566.  
  24567.                 IF @@ERROR <> 0 OR @retcode <> 0
  24568.                     goto UNDO
  24569.  
  24570.                 -- Raise a warning. Snapshot is invalidated. Need to run
  24571.                 -- snapshot agent again..
  24572.                 raiserror(20605, 10, -1)
  24573.             end
  24574.         end
  24575.     end
  24576.     
  24577.     if @need_reinit_subscription = 1
  24578.     begin
  24579.         -- Reinitialize the subscriptions if there are any.
  24580.         -- No need to reinit no_sync subscriptions.
  24581.         -- The query below works for an article or whole publication (@artid == 0)
  24582.         -- Including virtual subscriptions to take care anonymous.
  24583.         if exists (select * from syssubscriptions s where
  24584.             s.status = @active and
  24585.             -- Only include virtual subscription if allow anonymous
  24586.             (s.srvid >= 0 or (@allow_anonymous = 1 and @immediate_sync_ready = 1)) and
  24587.             s.sync_type <> @none and
  24588.             (s.artid = @artid or 
  24589.             (@artid = 0 and exists (select * from 
  24590.                 syspublications p, sysarticles a where
  24591.                 a.artid = s.artid and 
  24592.                 a.pubid = p.pubid and
  24593.                 p.pubid = @pubid))))
  24594.         begin
  24595.             -- Fail and raiserror error
  24596.             if @force_reinit_subscription = 0
  24597.             begin
  24598.                 raiserror(20608, 16, -1)
  24599.                 goto UNDO
  24600.             end
  24601.  
  24602.             if @check_only = 0
  24603.             begin
  24604.                 EXEC @retcode = dbo.sp_reinitsubscription 
  24605.                     @publication = @publication, 
  24606.                     @article = @article,
  24607.                     @subscriber = 'all',
  24608.                     @for_schema_change = 1
  24609.                 IF @@ERROR <> 0 OR @retcode <> 0
  24610.                 BEGIN
  24611.                     GOTO UNDO
  24612.                 END
  24613.                 -- Raise a warning. Subscriptions is reintialized.
  24614.                 raiserror(20606, 10, -1)
  24615.             end
  24616.         end
  24617.     end
  24618.  
  24619.     COMMIT TRAN sp_MSreinit_article
  24620.     
  24621.     return 0
  24622. UNDO:
  24623.     IF @@TRANCOUNT > 0
  24624.     begin
  24625.         ROLLBACK TRAN sp_MSreinit_article
  24626.         COMMIT TRAN 
  24627.     end
  24628.     return 1
  24629. go
  24630.  
  24631. EXEC dbo.sp_MS_marksystemobject sp_MSreinit_article
  24632. GO
  24633.  
  24634.  
  24635. print ''
  24636. print 'Creating procedure sp_MScomputearticlescreationorder'
  24637. go
  24638. CREATE PROCEDURE sp_MScomputearticlescreationorder
  24639.     @publication sysname
  24640. AS
  24641.     SET NOCOUNT ON
  24642.     DECLARE @pubid int 
  24643.     DECLARE @max_level int
  24644.     DECLARE @current_level int
  24645.     DECLARE @update_level int
  24646.     DECLARE @limit int
  24647.     DECLARE @result int
  24648.  
  24649.     SELECT @pubid = NULL
  24650.     -- Get the pubid from syspublications 
  24651.     SELECT @pubid = pubid 
  24652.       FROM syspublications
  24653.      WHERE name = @publication
  24654.  
  24655.     IF @@ERROR <> 0
  24656.         RETURN (1)
  24657.  
  24658.     IF @pubid IS NULL
  24659.     BEGIN
  24660.         RAISERROR(20026, 16, -1, @publication)
  24661.         RETURN (1)
  24662.     END
  24663.  
  24664.     EXEC @result = sp_getapplock @Resource = @publication, 
  24665.                 @LockMode = N'Shared', 
  24666.                 @LockOwner = N'Session', 
  24667.                 @LockTimeout = 0
  24668.  
  24669.     IF @result < 0
  24670.     BEGIN
  24671.         RAISERROR(21385, 16, -1, @publication)
  24672.         RETURN (1)
  24673.     END
  24674.  
  24675.     -- Find out the total number of articles in this publication and
  24676.     -- compute the maximum tree height based on the number of articles in 
  24677.     -- the publication. Here, the tree height is counted from the
  24678.     -- leaf-nodes towards the root(s)
  24679.     SELECT @max_level = COUNT(*) + 10,
  24680.            @limit =2 *  COUNT(*) + 11 
  24681.       FROM sysextendedarticlesview 
  24682.      WHERE pubid = @pubid
  24683.  
  24684.     IF @@ERROR <> 0
  24685.     BEGIN
  24686.         RETURN (1)
  24687.     END
  24688.    
  24689.     -- The following temp table contains the minimal amount of 
  24690.     -- article information that we want to keep around and the current
  24691.     -- computed tree level of the article
  24692.     CREATE TABLE #article_level_info
  24693.     (
  24694.         article         sysname collate database_default not null,
  24695.         source_objid    INT     NOT NULL,
  24696.         tree_level      INT     NOT NULL,
  24697.         ref_level       INT     NOT NULL,
  24698.         major_type      TINYINT NOT NULL  -- 1-view&func, 0-other 
  24699.     )  
  24700.    
  24701.     CREATE CLUSTERED INDEX ucarticle_level_info 
  24702.         ON #article_level_info(source_objid)
  24703.  
  24704.     IF @@ERROR <> 0
  24705.     BEGIN
  24706.         GOTO Failure
  24707.     END
  24708.  
  24709.     -- Populate the article level info table. All articles will be
  24710.     -- assigned 0 as their initial tree level. Having 
  24711.     -- a tree level of 0 means that the algorithm hasn't discovered 
  24712.     -- any objects that the article depends on within the publication.
  24713.  
  24714.     INSERT INTO #article_level_info 
  24715.     SELECT name, objid, 0, 0, 
  24716.         CASE type    
  24717.             WHEN 0x40 THEN 1
  24718.             WHEN 0x80 THEN 1
  24719.             ELSE 0 
  24720.         END
  24721.       FROM sysextendedarticlesview
  24722.      WHERE pubid = @pubid
  24723.       
  24724.     -- To jump-start the algorithm, update the tree_level of 
  24725.     -- all articles with no dependency to @max_level.
  24726.  
  24727.     UPDATE #article_level_info 
  24728.        SET tree_level = @max_level
  24729.      WHERE NOT EXISTS (SELECT * 
  24730.                          FROM sysdepends 
  24731.                         WHERE source_objid = id)
  24732.     IF @@ERROR <> 0
  24733.         GOTO Failure
  24734.  
  24735.     -- For each increasing tree level starting from @max_level, update the 
  24736.     -- the tree_level of articles depending on objects at the current
  24737.     -- level to current level + 1
  24738.     SELECT @current_level = @max_level
  24739.     WHILE 1 = 1
  24740.     BEGIN
  24741.         SELECT @update_level = @current_level + 1
  24742.  
  24743.         UPDATE #article_level_info
  24744.            SET tree_level = @update_level
  24745.           FROM #article_level_info 
  24746.         INNER JOIN sysdepends d
  24747.             ON #article_level_info.source_objid = d.id 
  24748.         INNER JOIN #article_level_info ali1
  24749.             ON (d.depid = ali1.source_objid       
  24750.                AND ali1.tree_level = @current_level)
  24751.     
  24752.         -- Terminate the algorithm if we cannot find any articles 
  24753.         -- depending on articles at the current level     
  24754.         IF @@ROWCOUNT = 0
  24755.             GOTO PHASE1
  24756.  
  24757.         IF @@ERROR <> 0
  24758.             GOTO Failure
  24759.  
  24760.         SELECT @current_level = @current_level + 1
  24761.  
  24762.         -- Although there should not be any circular 
  24763.         -- dependencies among the articles, the following
  24764.         -- check is performed to guarantee that 
  24765.         -- the algorithm will terminate even if there 
  24766.         -- is circular dependency among the articles
  24767.         
  24768.         -- Note that with at least one node per level,
  24769.         -- the current level can never exceed the total 
  24770.         -- number of articles (nodes) unless there is
  24771.         -- circular dependency among the articles.
  24772.         
  24773.         -- @limit is defined to be # of articles + 1
  24774.         -- although @limit = # of articles - 1 will be
  24775.         -- sufficient. This is to make absolutely sure that 
  24776.         -- the algorithm will never terminate too early
  24777.  
  24778.         IF @current_level > @limit
  24779.             GOTO PHASE1
  24780.     END
  24781.  
  24782. PHASE1:
  24783.  
  24784.     -- There may be interdependencies among articles 
  24785.     -- that haven't been included in the previous calculations so
  24786.     -- we compute the proper order among these articles here.
  24787.     SELECT @limit = @max_level - 9
  24788.     SELECT @current_level = 0
  24789.     WHILE 1 = 1
  24790.     BEGIN
  24791.         SELECT @update_level = @current_level + 1
  24792.         
  24793.         UPDATE #article_level_info 
  24794.            SET tree_level = @update_level
  24795.           FROM #article_level_info
  24796.         INNER JOIN sysdepends d
  24797.             ON (#article_level_info.source_objid = d.id
  24798.                 AND #article_level_info.tree_level < @max_level) 
  24799.         INNER JOIN #article_level_info ali1
  24800.             ON (d.depid = ali1.source_objid
  24801.                 AND ali1.tree_level = @current_level)
  24802.         IF @@ROWCOUNT = 0
  24803.             GOTO PHASE2
  24804.         
  24805.         IF @@ERROR <> 0
  24806.             GOTO Failure
  24807.  
  24808.         SELECT @current_level = @current_level + 1
  24809.         IF @current_level > @limit
  24810.             GOTO PHASE2
  24811.     END         
  24812.  
  24813. PHASE2:
  24814.  
  24815.     -- Since transactional doesn't keep the nickname around in 
  24816.     -- sysmergearticles as merge does, we need to compute FK/PK ordering on 
  24817.     -- the fly. 
  24818.     SELECT @current_level = 0
  24819.     SELECT @limit = @max_level - 9
  24820.     WHILE 1 = 1
  24821.     BEGIN
  24822.         SELECT @update_level = @current_level + 1
  24823.         
  24824.         UPDATE #article_level_info
  24825.            SET ref_level = @update_level
  24826.           FROM #article_level_info
  24827.         INNER JOIN sysreferences r
  24828.             ON #article_level_info.source_objid = r.fkeyid
  24829.         INNER JOIN #article_level_info ali1
  24830.             ON (r.rkeyid = ali1.source_objid 
  24831.                 AND ali1.ref_level = @current_level)
  24832.         IF @@ROWCOUNT = 0
  24833.             GOTO PHASE3
  24834.  
  24835.         IF @@ERROR <> 0
  24836.             GOTO Failure
  24837.  
  24838.         SELECT @current_level = @current_level + 1
  24839.         IF @current_level > @limit
  24840.             GOTO PHASE3
  24841.     END
  24842.  
  24843. PHASE3:
  24844.  
  24845.     -- Select the articles out of #article_level_info 
  24846.     -- in ascending order of tree_level. This will give
  24847.     -- the proper order in which articles can be created
  24848.     -- without violating the internal dependencies among
  24849.     -- themselves. Note that this algorithm still allows 
  24850.     -- unresolved external references outside the publication.
  24851.     -- All this algorithm can guarantee is that all articles will
  24852.     -- be created successfully using the resulting order if 
  24853.     -- there is no dependent object outside the publication. 
  24854.     -- We need to order the articles in reverse ref_level
  24855.     -- to account for FK/PK constraints when dropping/deleting rows/truncating
  24856.     -- tables on the Subscriber.
  24857.  
  24858.     SELECT article
  24859.       FROM #article_level_info
  24860.     ORDER BY major_type ASC, tree_level ASC, ref_level DESC
  24861.  
  24862.     DROP TABLE #article_level_info
  24863.     RETURN (0)
  24864.  
  24865. Failure:
  24866.  
  24867.     DROP TABLE #article_level_info
  24868.     RETURN (1)
  24869. GO
  24870.  
  24871. exec dbo.sp_MS_marksystemobject sp_MScomputearticlescreationorder
  24872. go
  24873.  
  24874. print ''
  24875. print 'Creating procedure sp_MScomputeunresolvedrefs'
  24876. go
  24877. CREATE PROCEDURE sp_MScomputeunresolvedrefs
  24878.     @publication sysname, -- Must provide the publication name
  24879.     @article     sysname = '%' -- '%' means all articles in the specified publication, otherwise an exact match is performed
  24880. AS
  24881.     SET NOCOUNT ON 
  24882.     DECLARE @pubid int 
  24883.     
  24884.     -- Parameter check: @publication
  24885.  
  24886.     IF @publication IS NULL
  24887.     BEGIN
  24888.         RAISERROR (14043, 16, -1, '@publication')
  24889.         RETURN (1)
  24890.     END
  24891.  
  24892.     SELECT @pubid = NULL 
  24893.     -- Get the pubid of the publication
  24894.     SELECT @pubid = pubid 
  24895.       FROM syspublications
  24896.      WHERE name = @publication
  24897.     
  24898.     IF @pubid IS NULL
  24899.     BEGIN
  24900.         RAISERROR (20026, 11, -1, @publication)
  24901.         RETURN (1)    
  24902.     END
  24903.  
  24904.     SELECT DISTINCT 
  24905.            'article' = a.name, 
  24906.            'dependent object' = o.name, 
  24907.            'dependent object owner' = u.name, 
  24908.            'dependent objectid' = o.id 
  24909.       FROM dbo.sysextendedarticlesview a
  24910.     INNER JOIN sysdepends dep
  24911.         ON a.objid = dep.id
  24912.        AND a.pubid = @pubid
  24913.        AND (@article = '%' OR name = @article)
  24914.        AND dep.depid NOT IN (SELECT objid FROM dbo.sysextendedarticlesview
  24915.                               WHERE pubid = @pubid 
  24916.                                 AND (@article = '%' OR name = @article))
  24917.     INNER JOIN sysobjects o
  24918.         ON dep.depid = o.id
  24919.     INNER JOIN sysusers u
  24920.         ON u.uid = o.uid          
  24921. GO
  24922.  
  24923.  
  24924. exec dbo.sp_MS_marksystemobject sp_MScomputeunresolvedrefs
  24925. go
  24926.  
  24927. /*
  24928.  * Name :       sp_MShelptranconflictpublications
  24929.  * Called by:    sp_MShelpconflictpublications
  24930.  * Description: This sp returns a list of queued publications or subscriptions in the current
  24931.  *    database that may have conflicts. Results are ordered by publication
  24932.  *    name. * Parameters:  1. publication_type( sysname; '%'==ALL  | 'queued' )
  24933.  * Output Result Set has the following structure:
  24934.  *  
  24935. ----------------------------------------------------------------------------------
  24936.  *      Name                Datatype                Description
  24937.  *  
  24938. ----------------------------------------------------------------------------------
  24939.  *  a. name     (sysname)      Publication name
  24940.  *  b. publication_type  (varchar(9))  'merge' | 'queued' | 'immediate' (reserved)
  24941.  *  c. merge_pub_id   (uniqueidentifier) Merge publication identifier
  24942.  *  d. tran_pub_id  (integer)   Queued publication identifier 
  24943.  *  e. sub_agent_id    (integer)    Unique publication identifier on a tran subscriber
  24944.  *  NOTE: In case of queued tran publications, either d or e will have a value at any time
  24945.  *  and this will also indicate, if we are processing a subscriber of a publication (d 
  24946.  *  will be NULL and e will have a value) or if we are processing the publisher side (d
  24947.  *  will have a value and e will be NULL)
  24948.  */ 
  24949.  
  24950. raiserror('Creating procedure sp_MShelptranconflictpublications', 0,1)
  24951. GO
  24952.  
  24953. create procedure sp_MShelptranconflictpublications (
  24954.      @publication_type    sysname = 'queued' )        -- '%'==ALL | 'queued'
  24955. as
  24956. begin
  24957.     set nocount on
  24958.     declare @merge_pub_id uniqueidentifier
  24959.     
  24960.     --
  24961.     -- validate
  24962.     --
  24963.     if (@publication_type NOT IN ('%', 'queued'))
  24964.     begin
  24965.         raiserror('sp_MShelptranconflictpublications(debug): Invalid @publication_type=%s specified', 16, 1, @publication_type)
  24966.         return (1)
  24967.     end
  24968.         
  24969.     --
  24970.     -- create a temp table for results
  24971.     --
  24972.      create table #cftpublications ( publication sysname collate database_default, t_pub_id integer, s_agent_id integer)
  24973.  
  24974.      --
  24975.      -- process publisher info
  24976.      --
  24977.      if exists (select * from sysobjects where name = 'syspublications')
  24978.      begin
  24979.          insert into #cftpublications(publication, t_pub_id)
  24980.              select name, pubid from syspublications
  24981.          if (@@error != 0)
  24982.          begin
  24983.             raiserror('sp_MShelptranconflictpublications(debug): insert for tran publications failed', 16, 1)
  24984.             return (1)
  24985.          end
  24986.      end
  24987.  
  24988.      --
  24989.      -- process subscriber info
  24990.      --
  24991.      if exists (select * from sysobjects where name = 'MSsubscription_agents')
  24992.      begin
  24993.          insert into #cftpublications(publication, s_agent_id)
  24994.              select publication, id from MSsubscription_agents where update_mode in (2,3,4,5)
  24995.      end
  24996.  
  24997.      --
  24998.      -- now do a select on the temp table
  24999.      --
  25000.      select    'name'                = publication,
  25001.              'publication_type'    = N'queued',
  25002.              'merge_pub_id'         = @merge_pub_id,
  25003.              'tran_pub_id'         = t_pub_id,
  25004.              'sub_agent_id'        = s_agent_id
  25005.      from     #cftpublications
  25006.              
  25007.      --
  25008.      -- all done
  25009.      --
  25010.      return 0
  25011. end
  25012. go
  25013.  
  25014. exec dbo.sp_MS_marksystemobject sp_MShelptranconflictpublications
  25015. go
  25016.  
  25017. /*
  25018.  * Name :       sp_MShelptranconflictcounts
  25019.  * Description: This sp returns the count of conflicts (from each conflict table) in 
  25020.  *    each publication. Results can optionally be filtered to include only a 
  25021.  *    single publication. Results are always ordered by article name. Only 
  25022.  *    articles with non-zero conflict counts are returned.
  25023.  * Parameters:  1. Publication Name( sysname; default '%'==ALL PUBLICATIONS)
  25024.  * Output Result Set has the following structure:
  25025.  *  
  25026. ----------------------------------------------------------------------------------
  25027.  *      Name                Datatype                Description
  25028.  *  
  25029. ----------------------------------------------------------------------------------
  25030.  *  a. article    (nvarchar(256))      owner qualified Article name
  25031.  *  b. conflict_table  (sysname)   Associated conflict table (owner qualified)
  25032.  *  c. queued_source_proc (sysname)   Queued proc to get source row - sp_MSgettrancftsrcrow
  25033.  *  d. centralized_conflicts(bit)    Centralized (1) or Decentralized (0) 
  25034.  *            conflicts specified by the article
  25035.  *  e. conflict_count  (integer)           Count of (insert, update and delete) conflicts in 
  25036.  *            the conflict table for this article
  25037.  */
  25038. raiserror('Creating procedure sp_MShelptranconflictcounts', 0,1)
  25039. GO
  25040.  
  25041. create procedure sp_MShelptranconflictcounts ( 
  25042.     @publication_name sysname = '%' )
  25043. as 
  25044. begin
  25045.     set nocount on 
  25046.  
  25047.     declare @pubid int
  25048.             ,@centralized_conflicts bit
  25049.             ,@article sysname
  25050.             ,@artid int
  25051.             ,@conflict_table sysname
  25052.             ,@cft_tabid int
  25053.             ,@spname sysname
  25054.             ,@cmd nvarchar(4000)
  25055.             ,@conflicts_count int
  25056.             ,@publisher sysname
  25057.             ,@publisher_db sysname
  25058.             ,@owner sysname
  25059.  
  25060.     select @spname = 'sp_MSgettrancftsrcrow'
  25061.  
  25062.     --
  25063.     -- create temp table for results
  25064.     --
  25065.     create table #result_list ( article nvarchar(256) collate database_default, conflict_table sysname collate database_default null,  
  25066.         centralized_conflicts bit, conflict_count integer)
  25067.  
  25068.     create table #conflict_list ( artid sysname collate database_default, conflict_count int, sub_agent_id int )
  25069.  
  25070.     -- 
  25071.     -- process publisher
  25072.     --
  25073.     if exists ( select * from sysobjects where name = 'sysarticles')
  25074.     begin
  25075.         --
  25076.         -- Walk through each publication that allows queued operation
  25077.         --
  25078.         if ( @publication_name = '%' )
  25079.             declare hCPubCursor CURSOR LOCAL FAST_FORWARD fast_forward for
  25080.                 select pubid, centralized_conflicts
  25081.                 from syspublications
  25082.                 where allow_queued_tran = 1
  25083.         else
  25084.             declare hCPubCursor CURSOR LOCAL FAST_FORWARD fast_forward for
  25085.                 select pubid, centralized_conflicts
  25086.                 from syspublications
  25087.                 where allow_queued_tran = 1
  25088.                     and name = @publication_name
  25089.  
  25090.         open hCPubCursor
  25091.         fetch hCPubCursor into @pubid, @centralized_conflicts
  25092.         while ( @@fetch_status != -1 )
  25093.         begin
  25094.             --
  25095.             -- Walk through each article in this publication
  25096.             --
  25097.             declare hCArtCursor CURSOR LOCAL FAST_FORWARD fast_forward for
  25098.                 select a.name, b.conflict_tableid, a.artid
  25099.                 from sysarticles a join
  25100.                     sysarticleupdates b on
  25101.                         a.artid = b.artid and
  25102.                         a.pubid = b.pubid
  25103.                 where a.pubid = @pubid
  25104.  
  25105.             open hCArtCursor
  25106.             fetch hCArtCursor into @article, @cft_tabid, @artid
  25107.             while ( @@fetch_status != -1 )
  25108.             begin
  25109.                 --
  25110.                 -- get the owner qualified conflict table name
  25111.                 --
  25112.                 select @owner = QUOTENAME(user_name(OBJECTPROPERTY(@cft_tabid, 'OwnerId')))
  25113.                 select @conflict_table = @owner + N'.' + QUOTENAME(OBJECT_NAME(@cft_tabid))
  25114.  
  25115.                 --
  25116.                 -- Get all the conflict counts
  25117.                 --
  25118.                 select @cmd = 'select ' + cast(@artid as nvarchar(10)) +  
  25119.                     ', count(*) from ' + @conflict_table + 
  25120.                     ' where conflict_type in (1, 5, 7) and pubid = ' + 
  25121.                     cast(@pubid as nvarchar(10))
  25122.                 insert into #conflict_list ( artid, conflict_count )
  25123.                     exec ( @cmd )
  25124.  
  25125.                 select @conflicts_count = NULLIF(conflict_count, 0)
  25126.                 from #conflict_list
  25127.                 where artid = @artid
  25128.                 
  25129.                 if (@conflicts_count > 0)
  25130.                 begin
  25131.                     --
  25132.                     -- add a row to the #result_list
  25133.                     --
  25134.                     insert into #result_list ( article, conflict_table, centralized_conflicts, conflict_count )
  25135.                         select @owner + N'.' + QUOTENAME(@article), @conflict_table, @centralized_conflicts, @conflicts_count
  25136.                 end
  25137.                 
  25138.                 --
  25139.                 -- fetch next row from hCArtCursor
  25140.                 --
  25141.                 fetch hCArtCursor into @article, @cft_tabid, @artid
  25142.             end
  25143.             close hCArtCursor
  25144.             deallocate hCArtCursor
  25145.  
  25146.             --
  25147.             -- fetch next row from hCPubCursor
  25148.             --
  25149.             fetch hCPubCursor into @pubid, @centralized_conflicts    
  25150.         end
  25151.         close hCPubCursor
  25152.         deallocate hCPubCursor
  25153.     end
  25154.  
  25155.     --
  25156.     -- process subscriber side
  25157.     --
  25158.     delete #conflict_list
  25159.     if exists ( select * from sysobjects where name = 'MSsubscription_articles')
  25160.     begin
  25161.         --
  25162.         -- Walk through each subscription that allows queued operation
  25163.         --
  25164.         if ( @publication_name = '%' )
  25165.             declare hCPubCursor CURSOR LOCAL FAST_FORWARD fast_forward for
  25166.                 select id, 0, publisher, publisher_db 
  25167.                 from MSsubscription_agents 
  25168.                 where update_mode in (2,3,4,5)
  25169.         else
  25170.             declare hCPubCursor CURSOR LOCAL FAST_FORWARD fast_forward for
  25171.                 select id, 0, publisher, publisher_db 
  25172.                 from MSsubscription_agents 
  25173.                 where update_mode in (2,3,4,5)
  25174.                     and publication = @publication_name
  25175.  
  25176.         open hCPubCursor
  25177.         fetch hCPubCursor into @pubid, @centralized_conflicts, @publisher, @publisher_db
  25178.         while ( @@fetch_status != -1 )
  25179.         begin
  25180.             --
  25181.             -- Walk through each article in this subscribed publication
  25182.             --
  25183.             declare hCArtCursor CURSOR LOCAL FAST_FORWARD fast_forward for
  25184.                 select a.article, OBJECT_ID(a.cft_table), a.artid
  25185.                 from MSsubscription_articles a join
  25186.                     MSsubscription_agents b on
  25187.                         a.agent_id = b.id
  25188.                 where b.id = @pubid
  25189.  
  25190.             open hCArtCursor
  25191.             fetch hCArtCursor into @article, @cft_tabid, @artid
  25192.             while ( @@fetch_status != -1 )
  25193.             begin
  25194.                 --
  25195.                 -- get the owner qualified conflict table name
  25196.                 --
  25197.                 select @owner = QUOTENAME(user_name(OBJECTPROPERTY(@cft_tabid, 'OwnerId')))
  25198.                 select @conflict_table = @owner + N'.' + QUOTENAME(OBJECT_NAME(@cft_tabid))
  25199.  
  25200.                 --
  25201.                 -- Get all the conflict counts
  25202.                 --
  25203.                 select @cmd = 'select ' + cast(@artid as nvarchar(10)) +  
  25204.                     ', count(*), ' + cast(@pubid as nvarchar(10)) + 
  25205.                     ' from ' + @conflict_table + 
  25206.                     ' where conflict_type in (1, 5, 7) 
  25207.                         and origin_datasource = ''' + @publisher + '.' + @publisher_db + ''''
  25208.                     
  25209.                 insert into #conflict_list ( artid, conflict_count, sub_agent_id )
  25210.                     exec ( @cmd )
  25211.  
  25212.                 select @conflicts_count = NULLIF(conflict_count, 0)
  25213.                 from #conflict_list
  25214.                 where artid = @artid and sub_agent_id = @pubid
  25215.                 
  25216.                 if (@conflicts_count > 0)
  25217.                 begin
  25218.                     --
  25219.                     -- add a row to the #result_list
  25220.                     --
  25221.                     insert into #result_list ( article, conflict_table, centralized_conflicts, conflict_count )
  25222.                         select @owner + N'.' + QUOTENAME(@article), @conflict_table, @centralized_conflicts, @conflicts_count
  25223.                 end
  25224.                 
  25225.                 --
  25226.                 -- fetch next row from hCArtCursor
  25227.                 --
  25228.                 fetch hCArtCursor into @article, @cft_tabid, @artid
  25229.             end
  25230.             close hCArtCursor
  25231.             deallocate hCArtCursor
  25232.  
  25233.             --
  25234.             -- fetch next row from hCPubCursor
  25235.             --
  25236.             fetch hCPubCursor into @pubid, @centralized_conflicts, @publisher, @publisher_db    
  25237.         end
  25238.         close hCPubCursor
  25239.         deallocate hCPubCursor
  25240.     end
  25241.  
  25242.     --
  25243.     -- do a select for results
  25244.     --
  25245.     select     article,
  25246.             conflict_table,
  25247.             'queued_source_proc' = @spname,
  25248.             centralized_conflicts,
  25249.             conflict_count
  25250.     from #result_list
  25251.  
  25252.     --
  25253.     -- all done
  25254.     --
  25255.     return (0)
  25256. end
  25257. go
  25258.  
  25259. exec dbo.sp_MS_marksystemobject sp_MShelptranconflictcounts
  25260. go 
  25261.  
  25262. /*
  25263.  * Name :       sp_MSgettranconflictrow
  25264.  * Description: This sp returns a result set containing the requested conflict row(s) 
  25265.  *    for a queued publication. Result set ordered by transaction id and 
  25266.  *    row identifier.
  25267.  * Parameters:  
  25268.  *      1. tran_id    nvarchar(70). ('%'==ALL transactions for the article)
  25269.  *    2. row_id ( uniqueidentifer or '%'==ALL rows for a given transaction)
  25270.  *    3. conflict_table    (sysname)
  25271.  * Output Result Set has the following structure:
  25272.  *  
  25273. ----------------------------------------------------------------------------------
  25274.  *      Name                Datatype                Description
  25275.  *  
  25276. ----------------------------------------------------------------------------------
  25277.  * returns the current row (all columns) from conflict table with specified tran_id, (row_id)insert_date
  25278.  */
  25279. raiserror('Creating procedure sp_MSgettranconflictrow', 0,1)
  25280. GO
  25281.  
  25282. create procedure sp_MSgettranconflictrow ( 
  25283.     @tran_id sysname = '%',                        -- % = ALL
  25284.     @row_id sysname = '%',                        -- % = ALL
  25285.     @conflict_table sysname)
  25286. as 
  25287. begin
  25288.     set nocount on
  25289.     declare @cmd nvarchar(4000)
  25290.             ,@whcmd nvarchar(4000)
  25291.  
  25292.     select @cmd = N'select * from ' + @conflict_table 
  25293.     if (@tran_id != N'%')
  25294.     begin
  25295.         if (@whcmd is null)
  25296.             select @whcmd = N'tranid = ''' + @tran_id + N''''
  25297.         else
  25298.             select @whcmd = @whcmd + N' and tranid = ''' + @tran_id + N''''        
  25299.     end
  25300.     if (@row_id != N'%')
  25301.     begin
  25302.         if (@whcmd is null)
  25303.             select @whcmd = N'qcfttabrowid = ''' + @row_id + N''''
  25304.         else
  25305.             select @whcmd = @whcmd + N' and qcfttabrowid = ''' + @row_id + N''''
  25306.     end
  25307.  
  25308.     if (@whcmd is not null)
  25309.     begin
  25310.         select @cmd = @cmd + N' where ' + @whcmd
  25311.     end
  25312.     
  25313.     execute (@cmd)
  25314. end
  25315. go
  25316.  
  25317. exec dbo.sp_MS_marksystemobject sp_MSgettranconflictrow
  25318. go
  25319.  
  25320. /*
  25321.  * Name :       sp_MSgettrancftsrcrow
  25322.  * Description: This sp returns a result set containing the requested source row 
  25323.  *     pertaining to a respective conflict row in conflict table (same PK/unique key)
  25324.  *     for a queued publication. Result set ordered by transaction id and row identifier
  25325.  *       for the conflict table.
  25326.  * Parameters:  1. tran_id (nvarchar(70))
  25327.  *      2. row_id uniqueidentifer - cannot be null
  25328.  *    3. conflict_table (nvarchar(256) - owner qualified table name - [owner].[tabname]
  25329.  *      4. is_subscriber bit=0                        -- Publisher = 0, Subscriber = 1
  25330.  * Output Result Set has the following structure:
  25331.  *  
  25332. ----------------------------------------------------------------------------------
  25333.  *      Name                Datatype                Description
  25334.  *  
  25335. ----------------------------------------------------------------------------------
  25336.  * returns the current row (all columns) from from source table with same PK for the row in 
  25337.  * conflict table with specified tran_id, insert_date
  25338.  */
  25339. raiserror('Creating procedure sp_MSgettrancftsrcrow', 0,1)
  25340. GO
  25341.  
  25342. create procedure sp_MSgettrancftsrcrow ( 
  25343.     @tran_id sysname,
  25344.     @row_id sysname,
  25345.     @conflict_table nvarchar(256),
  25346.     @is_subscriber bit,
  25347.     @is_debug bit=0 )
  25348. as 
  25349. begin
  25350.     set nocount on
  25351.     declare @decllist nvarchar(4000)
  25352.             ,@sellist nvarchar(4000)
  25353.             ,@wherelist nvarchar(4000)
  25354.             ,@cmd nvarchar(4000)
  25355.             ,@cmdrow nvarchar(4000)
  25356.             ,@srctable sysname
  25357.             ,@srctabid int
  25358.             ,@srcowner sysname
  25359.             ,@columns  binary(32)
  25360.             ,@indid int
  25361.             ,@indkey int
  25362.             ,@key sysname
  25363.             ,@this_col int
  25364.             ,@col sysname
  25365.             ,@typestring nvarchar(60)
  25366.             ,@dbname sysname
  25367.             ,@retcode smallint
  25368.             ,@unqualified_cft_tab sysname
  25369.             ,@startoffset int
  25370.             
  25371.     --
  25372.     -- validate
  25373.     --
  25374.     if ((@tran_id is null) or (@row_id is null) or 
  25375.         (@conflict_table is null) or (@is_subscriber is null))
  25376.     begin
  25377.         raiserror('sp_MSgettrancftsrcrow(debug): @tran_id,@row_id,@conflict_table,@is_subscriber cannot be null', 16, 1)
  25378.         return (1)
  25379.     end
  25380.  
  25381.     --
  25382.     -- check if the conflict table is owner qualified
  25383.     --
  25384.     select @startoffset = charindex(N'].[', @conflict_table, 0)
  25385.     select @unqualified_cft_tab = case when (@startoffset > 0) 
  25386.         then substring(@conflict_table, @startoffset + 2, len(@conflict_table) - @startoffset - 1)
  25387.         else quotename(@conflict_table) end
  25388.         
  25389.     --
  25390.     -- get the source table info
  25391.     --
  25392.     if (@is_subscriber = 1)
  25393.     begin
  25394.         select @srcowner = owner, @srctable = dest_table, 
  25395.             @srctabid = OBJECT_ID(dest_table), @columns = columns
  25396.         from MSsubscription_articles
  25397.         where quotename(cft_table) = @unqualified_cft_tab
  25398.     end
  25399.     else
  25400.     begin
  25401.         select @srcowner = user_name(OBJECTPROPERTY(objid,'OwnerId')), @srctable = OBJECT_NAME(objid), 
  25402.             @srctabid = objid, @columns = columns
  25403.         from sysarticles a join sysarticleupdates b on
  25404.             a.pubid = b.pubid and 
  25405.             a.artid = b.artid
  25406.         where b.conflict_tableid = OBJECT_ID(@conflict_table)
  25407.     end
  25408.  
  25409.     --
  25410.     -- create code for the following :
  25411.     -- select the row of conflict with given tranid and insertdate
  25412.     -- retrieve the values of the PK/UI columns for the source table from this row in cft_table
  25413.     -- select all columns from source table using the values in a where clause for PK/UI
  25414.     --
  25415.  
  25416.     --
  25417.     -- PK/UI check for source table
  25418.     --
  25419.     exec @indid = dbo.sp_MStable_has_unique_index @srctabid
  25420.     if (@indid = 0)
  25421.     begin
  25422.         raiserror('sp_MSgettrancftsrcrow(debug):source table %s does not have unique index', 16, 1, @srctable)
  25423.         return (1)
  25424.     end
  25425.  
  25426.     --
  25427.     -- create temp tables
  25428.     --
  25429.     create table #decltext ( c1 int identity NOT NULL, cmdtext nvarchar(4000) collate database_default null)
  25430.     create table #seltext ( c1 int identity NOT NULL, cmdtext nvarchar(4000) collate database_default null)
  25431.     create table #wheretext ( c1 int identity NOT NULL, cmdtext nvarchar(4000) collate database_default null)
  25432.  
  25433.     --
  25434.     -- walk through each column in PK/UI and build parts of code
  25435.     --
  25436.     select @indkey = 1
  25437.     while (@indkey <= 16)
  25438.     begin    
  25439.         select @key = index_col(@srctable, @indid, @indkey)
  25440.         if (@key is null)
  25441.         begin
  25442.             select @indkey = 16
  25443.         end
  25444.         else
  25445.         begin
  25446.             --
  25447.             -- get the column index in the source table for this index key
  25448.             --
  25449.             exec dbo.sp_MSget_col_position @srctabid, @columns, @key, @col output, @this_col output
  25450.  
  25451.             --
  25452.             -- get the typestring for this column in source table
  25453.             --
  25454.             exec dbo.sp_gettypestring @srctabid, @this_col, @typestring OUTPUT
  25455.  
  25456.             --
  25457.             -- build command strings
  25458.             --
  25459.             if (@decllist is NULL)
  25460.                 select @decllist = N'declare @' + @col + N' ' + @typestring
  25461.             else
  25462.                 select @decllist = N' ,@' + @col + N' ' + @typestring
  25463.             
  25464.             if (@sellist is NULL)
  25465.                 select @sellist = N'select @' + @col + N' = ' + quotename(@key)
  25466.             else
  25467.                 select @sellist = N' ,@' + @col + N' = ' + quotename(@key)
  25468.                 
  25469.             if (@wherelist is NULL)
  25470.                 select @wherelist = N'where ' + quotename(@key) + N' = @' + @col
  25471.             else
  25472.                 select @wherelist = N' ,' + quotename(@key) + N' = @' + @col
  25473.  
  25474.             --
  25475.             -- store them in the temp tables
  25476.             --
  25477.             insert into #decltext(cmdtext) values(@decllist)
  25478.             insert into #seltext(cmdtext) values(@sellist)
  25479.             insert into #wheretext(cmdtext) values(@wherelist)
  25480.             
  25481.         end
  25482.         select @indkey = @indkey + 1
  25483.     end
  25484.  
  25485.     --
  25486.     -- Now put all the code in order in the codetext
  25487.     --
  25488.     if exists (select * from sysobjects where name = 'MSsrcrow_codetext')
  25489.         drop table MSsrcrow_codetext
  25490.         
  25491.     create table MSsrcrow_codetext ( step int identity NOT NULL, cmdtext nvarchar(4000) NULL)
  25492.  
  25493.     insert into MSsrcrow_codetext(cmdtext)
  25494.         select cmdtext from #decltext order by c1
  25495.     insert into MSsrcrow_codetext(cmdtext) values (N' ')
  25496.     insert into MSsrcrow_codetext(cmdtext)
  25497.         select cmdtext from #seltext order by c1
  25498.     select @cmd = N' 
  25499.     from ' 
  25500.  
  25501.     if (@startoffset > 0)
  25502.         select @cmd = @cmd + @conflict_table
  25503.     else
  25504.         select @cmd = @cmd + quotename(@srcowner) + N'.' + @unqualified_cft_tab
  25505.         
  25506.     select @cmd = @cmd + N'
  25507.     where tranid = ''' + @tran_id + ''' and qcfttabrowid = ''' + @row_id + ''' '
  25508.     insert into MSsrcrow_codetext(cmdtext) values (@cmd)
  25509.     select @cmd = N'select * from ' + quotename(@srcowner) + N'.' + quotename(@srctable) + N' '
  25510.     insert into MSsrcrow_codetext(cmdtext) values (@cmd)
  25511.     insert into MSsrcrow_codetext(cmdtext)
  25512.         select cmdtext from #wheretext order by c1
  25513.  
  25514.     --
  25515.     -- now execute the code we just built
  25516.     --
  25517.     if (@is_debug = 0)
  25518.     begin
  25519.         --
  25520.         -- Build 139:
  25521.         -- NOTE xp_execresultset should work here but does not
  25522.         -- return for a long time. Using exec() - should revisit
  25523.         -- this for more stable builds
  25524.         --
  25525.         declare #srccursor cursor local FAST_FORWARD FOR 
  25526.         select cmdtext from MSsrcrow_codetext order by step 
  25527.         FOR READ ONLY
  25528.  
  25529.         select @cmd = N' '
  25530.         select @dbname = db_name()
  25531.         open #srccursor
  25532.         fetch #srccursor into @cmdrow
  25533.         while (@@FETCH_STATUS = 0)
  25534.         begin
  25535.             select @cmd = @cmd + @cmdrow
  25536.             fetch #srccursor into @cmdrow    
  25537.         end        
  25538.         close #srccursor
  25539.         deallocate #srccursor
  25540.         
  25541.         execute(@cmd)
  25542.         if (@@error != 0)
  25543.         begin
  25544.             raiserror('sp_MSgettrancftsrcrow(debug): execute() failed for [%s] in db [%s] ', 16, 1, @cmd, @dbname)
  25545.             return (1)
  25546.         end
  25547.  
  25548.     end
  25549.     else
  25550.         select cmdtext from MSsrcrow_codetext order by step 
  25551.  
  25552.     --
  25553.     -- all done
  25554.     --
  25555.     drop table MSsrcrow_codetext
  25556.     return 0
  25557. end
  25558. go
  25559.  
  25560. exec dbo.sp_MS_marksystemobject sp_MSgettrancftsrcrow
  25561. go
  25562.  
  25563. /*
  25564.  * Name :       sp_MSdeletetranconflictrow
  25565.  * Description: This sp deletes the requested conflict row(s) for a queued publication. 
  25566.  *    Can delete all conflicts in a transaction by specifying only tran_id.
  25567.  * Parameters:  1. tran_id    (nvarchar(70))
  25568.  *    2. row_id ( uniqueidentifier or '%'==ALL conflicts for a given transaction)
  25569.  * Output  None.
  25570.  *  
  25571. ----------------------------------------------------------------------------------
  25572.  *      Name                Datatype                Description
  25573.  *  
  25574. ----------------------------------------------------------------------------------
  25575.  */ 
  25576. raiserror('Creating procedure sp_MSdeletetranconflictrow', 0,1)
  25577. GO
  25578.  
  25579. create procedure sp_MSdeletetranconflictrow ( 
  25580.     @tran_id sysname,
  25581.     @row_id sysname = '%',                        -- % = ALL
  25582.     @conflict_table sysname)
  25583. as 
  25584. begin
  25585.     set nocount on
  25586.     declare @cmd nvarchar(4000)
  25587.  
  25588.     if (@conflict_table is NULL)
  25589.     begin
  25590.         raiserror('sp_MSdeletetranconflictrow(debug) - @conflict_table cannot be null', 16, 1)
  25591.         return (1)
  25592.     end
  25593.  
  25594.     select @cmd = 'delete ' + @conflict_table +
  25595.         ' where tranid = ''' + @tran_id + ''''
  25596.  
  25597.     if (@row_id != N'%')
  25598.     begin
  25599.         select @cmd = @cmd +
  25600.         ' and qcfttabrowid = ''' + @row_id + ''''
  25601.     end
  25602.     
  25603.     execute (@cmd)
  25604. end
  25605. go
  25606.  
  25607. exec dbo.sp_MS_marksystemobject sp_MSdeletetranconflictrow
  25608. go
  25609.  
  25610.  
  25611. raiserror('Creating procedure sp_MSexternalfkreferences', 0,1)
  25612. go
  25613.  
  25614. create procedure sp_MSexternalfkreferences
  25615.     @publication sysname,
  25616.     @article     sysname
  25617. as
  25618.     declare @pubid int
  25619.     declare @objid int
  25620.     declare @retcode int
  25621.  
  25622.     exec @retcode = dbo.sp_MSreplcheck_publish
  25623.     if @@ERROR <> 0 or @retcode <> 0
  25624.         return (1)
  25625.  
  25626.     select @pubid = pubid from dbo.syspublications where name = @publication
  25627.     select @objid = objid from dbo.sysarticles where pubid = @pubid and name = @article
  25628.  
  25629.     select rkeyid, fkeyid from dbo.sysreferences
  25630.         where fkeyid = @objid
  25631.           and rkeyid not in (select objid from dbo.sysarticles where pubid = @pubid)      
  25632. go
  25633. exec dbo.sp_MS_marksystemobject sp_MSexternalfkreferences
  25634. go
  25635.  
  25636. --
  25637. -- This proc is called by sync/queued tran generated article procs
  25638. -- to get the reinitialization status of a subscription for a given article
  25639. --
  25640. raiserror('Creating procedure sp_MSgetarticlereinitvalue', 0,1)
  25641. go
  25642. create procedure sp_MSgetarticlereinitvalue (
  25643.     @subscriber         sysname = NULL,
  25644.     @subscriberdb         sysname = NULL,
  25645.     @artid                 int = NULL, 
  25646.     @reinit                 int output
  25647. )
  25648. as
  25649. begin
  25650.     set NOCOUNT ON
  25651.     declare @orig_srvid int
  25652.     
  25653.     --
  25654.     -- return NULL if no parameters supplied
  25655.     --
  25656.     if ((@subscriber IS NULL) or (@subscriberdb IS NULL) or (@artid IS NULL))
  25657.     begin
  25658.         select @reinit = NULL
  25659.         return 1
  25660.     end
  25661.  
  25662.     select @orig_srvid = srvid from master.dbo.sysservers where UPPER(srvname) = UPPER(@subscriber) collate database_default
  25663.     select @reinit = queued_reinit 
  25664.     from syssubscriptions 
  25665.     where 
  25666.         artid = @artid 
  25667.         and srvid = @orig_srvid
  25668.         and dest_db = @subscriberdb
  25669.  
  25670.     -- All done
  25671.     return 0
  25672. end
  25673. go
  25674.  
  25675. exec dbo.sp_MS_marksystemobject sp_MSgetarticlereinitvalue
  25676. go
  25677.  
  25678. --
  25679. -- this proc is be used by queued tran UPDATE conflict resolution SPs. It
  25680. -- takes as input a given article and the update bitmask and decides if 
  25681. -- PRIMARY KEY update is taking place returns the following return codes
  25682. --    -1 : Error in execution
  25683. --      0 : Not a PK update
  25684. --     1 : PK update
  25685. --
  25686. raiserror('Creating procedure sp_MSispkupdateinconflict', 0,1)
  25687. go
  25688. create proc sp_MSispkupdateinconflict (
  25689.     @pubid int
  25690.     ,@artid int
  25691.     ,@bitmap varbinary(4000)
  25692. )
  25693. as
  25694. begin
  25695.     declare @retcode int
  25696.         ,@columns binary(32)
  25697.         ,@tabname sysname
  25698.         ,@tabid int
  25699.         ,@indid int
  25700.         ,@indkey int
  25701.         ,@key sysname
  25702.         ,@colid int
  25703.         ,@isset int
  25704.         ,@artcol int
  25705.         ,@bytepos int
  25706.         ,@bitpos int
  25707.  
  25708.     --
  25709.     -- initalize and validate
  25710.     --
  25711.     select @columns = [columns]
  25712.         ,@tabid = objid
  25713.         ,@indkey = 1
  25714.         ,@artcol = 0
  25715.     from dbo.sysarticles
  25716.     where (artid = @artid) and (pubid = @pubid)
  25717.  
  25718.     if (@tabid is null)
  25719.     begin
  25720.         raiserror('sp_MSispkupdateinconflict(Debug): invalid pub and article id : %s.%s', 
  25721.                 16, -1, @pubid, @artid)
  25722.         return -1
  25723.     end
  25724.     
  25725.     select @tabname = QUOTENAME(user_name(OBJECTPROPERTY(@tabid, 'OwnerId'))) collate database_default 
  25726.             + N'.' + QUOTENAME(object_name( @tabid )) collate database_default
  25727.  
  25728.     --
  25729.     -- get the Primary Key Index
  25730.     --
  25731.     select @indid = i.indid 
  25732.     from dbo.sysindexes i 
  25733.     where ((i.status & 2048) != 0) and (i.id = @tabid)
  25734.     if (@indid is null)
  25735.     begin
  25736.         raiserror('sp_MSispkupdateinconflict(Debug): Cannot find primary key for %s', 
  25737.                 16, -1, @tabname)
  25738.         return -1
  25739.     end
  25740.     
  25741.     --
  25742.     -- create an enumeration of all the columns that are part of PK
  25743.     --
  25744.     create table #pkcoltab(pkindex int identity, keyname sysname collate database_default not null)
  25745.     while (@indkey <= 16)
  25746.     begin
  25747.         select @key = index_col( @tabname, @indid, @indkey )
  25748.         if (@key is null)
  25749.             break
  25750.         else
  25751.             insert into #pkcoltab(keyname) values(@key)
  25752.  
  25753.         select @indkey = @indkey + 1
  25754.     end
  25755.  
  25756.     --
  25757.     -- now walk through each article col and if it is
  25758.     -- a part of PK, then check if the update bitmap bit 
  25759.     -- corresponding to any article column is set
  25760.     --
  25761.     DECLARE #hCColid CURSOR LOCAL FAST_FORWARD FOR 
  25762.         select colid, [name] from dbo.syscolumns 
  25763.         where id = @tabid order by colid asc
  25764.  
  25765.     OPEN #hCColid
  25766.     FETCH #hCColid INTO @colid, @key
  25767.     WHILE (@@fetch_status != -1)
  25768.     begin
  25769.         exec @isset = dbo.sp_isarticlecolbitset @colid, @columns
  25770.         if (@isset != 0)
  25771.         begin
  25772.             --
  25773.             -- this column is part of the article
  25774.             --
  25775.             select @artcol = @artcol + 1
  25776.             if exists (select * from #pkcoltab where keyname = @key)
  25777.             begin
  25778.                 --
  25779.                 -- this column is part of PK
  25780.                 --
  25781.                 select     @bytepos = 1 + (@artcol-1) / 8 
  25782.                     ,@bitpos = power(2, (@artcol-1) % 8 )
  25783.  
  25784.                 --
  25785.                 -- if the update bitmap has bit set then
  25786.                 -- then it is a PK update
  25787.                 --
  25788.                 if ((substring(@bitmap, @bytepos, 1) & @bitpos) = @bitpos)
  25789.                     return 1
  25790.             end
  25791.         end        
  25792.  
  25793.         --
  25794.         -- get the next column
  25795.         --
  25796.         FETCH #hCColid INTO @colid, @key
  25797.     end
  25798.     CLOSE #hCColid
  25799.     DEALLOCATE #hCColid
  25800.     drop table #pkcoltab
  25801.  
  25802.     --
  25803.     -- if we have reached here then it mean the update does not
  25804.     -- affect PK columns, cleanup and return
  25805.     --
  25806.     return 0
  25807. end
  25808. go
  25809.  
  25810. EXEC dbo.sp_MS_marksystemobject sp_MSispkupdateinconflict
  25811. GO
  25812.  
  25813. --
  25814. -- sp_ivindexhasnullcols
  25815. --
  25816. -- Proc to validate a indexed view - prior to enabling a indexed view
  25817. -- ,this proc is used to make sure the I.V. clustered index is unique
  25818. -- and does contain any column that can be NULL
  25819. -- 
  25820. -- Parameters:
  25821. --
  25822. --    @viewname sysname         name of the view
  25823. --    ,@fhasnullcols bit         value of 1 if view index has columns that allow NULL
  25824. --                            value of 0 otherwise (returns 0 if error in execution)
  25825. --
  25826. -- Returns:
  25827. --         0 if success
  25828. --        1 if failure
  25829. --
  25830. create proc sp_ivindexhasnullcols (
  25831.     @viewname sysname
  25832.     ,@fhasnullcols bit OUTPUT
  25833. )
  25834. as
  25835. begin
  25836.     declare    @f_ind_unique bit
  25837.             ,@f_ind_clustered bit
  25838.             ,@ivobject_id int
  25839.             ,@indkey int
  25840.             ,@key sysname
  25841.  
  25842.     --
  25843.     -- validate view object
  25844.     --
  25845.     select @ivobject_id = object_id(@viewname)
  25846.             ,@fhasnullcols = 0
  25847.             
  25848.     if (@ivobject_id IS NULL or @ivobject_id = 0)
  25849.     begin
  25850.         raiserror('sp_ivindexhasnullcols(debug): invalid view object [%s]', 16, 1, @viewname)
  25851.         return 1
  25852.     end
  25853.  
  25854.     --
  25855.     -- get the clustered index and validate
  25856.     --
  25857.     select @f_ind_unique = case (status & 2) when 0 then 0 else 1 end
  25858.             ,@f_ind_clustered = case (status & 16) when 0 then 0 else 1 end 
  25859.     from dbo.sysindexes
  25860.     where id = @ivobject_id and indid = 1
  25861.     
  25862.     if (@f_ind_unique != 1) or (@f_ind_clustered != 1)
  25863.     begin
  25864.         raiserror('sp_ivindexhasnullcols(debug): cannot find unique clustered index for the view [%s]', 16, 1, @viewname)
  25865.         return 1
  25866.     end
  25867.     
  25868.     --
  25869.     -- create an enumeration of all the columns that are part of the view index
  25870.     --
  25871.     create table #indcoltab(vindexcol int identity, keyname sysname collate database_default not null)
  25872.     select @indkey = 1
  25873.     while (@indkey <= 16)
  25874.     begin
  25875.         select @key = index_col( @viewname, 1, @indkey )
  25876.         if (@key is null)
  25877.             break
  25878.         else
  25879.             insert into #indcoltab(keyname) values(@key)
  25880.  
  25881.         select @indkey = @indkey + 1
  25882.     end
  25883.  
  25884.     --
  25885.     -- We should not have any column participating in this index
  25886.     -- that allows NULL if we do
  25887.     -- mark the output flag to TRUE
  25888.     --
  25889.     if exists (select * 
  25890.         from dbo.syscolumns 
  25891.         where id = @ivobject_id 
  25892.             and isnullable = 1
  25893.             and name in (select keyname from #indcoltab))
  25894.     begin
  25895.         select @fhasnullcols = 1
  25896.     end
  25897.  
  25898.     --
  25899.     -- all done, cleanup and return
  25900.     --
  25901.     drop table #indcoltab
  25902.     return 0
  25903. end
  25904. go
  25905.  
  25906. EXEC dbo.sp_MS_marksystemobject sp_ivindexhasnullcols
  25907. GO
  25908.  
  25909.  
  25910. --
  25911. -- fn_sqlvarbasetostr
  25912. --
  25913. -- UDF to generate string from a given sqlvariant using its base type.
  25914. -- This function is used by compensating commands and use special rules
  25915. -- for generating strings :
  25916. -- For datatypes - varchar, nvarchar, char, nchar, uniqueidenfier, 
  25917. -- datetime, smalldatetime, invalid date : The value is quoted with single
  25918. -- quotes and any embedded quotes are prefixed with single quote
  25919. -- For other datatypes - The value is not quoted
  25920. -- 
  25921. -- Parameters:
  25922. --    @ssvar sql_variant         input sqlvariant parameter (could be NULL)
  25923. --
  25924. -- Returns:
  25925. --     nvarchar(4000) NULL        generated string. Is NULL if input is NULL
  25926. --
  25927. create function dbo.fn_sqlvarbasetostr (
  25928.     @ssvar sql_variant
  25929. )
  25930. returns nvarchar(4000)
  25931. as
  25932. begin
  25933.     declare @pstrout nvarchar(4000)
  25934.             ,@basetype sysname
  25935.  
  25936.     select @basetype = CAST(SQL_VARIANT_PROPERTY ( @ssvar, 'BaseType' ) as nvarchar(255))
  25937.     if (@ssvar IS NOT NULL and @basetype IS NOT NULL)
  25938.     begin
  25939.         if (lower(@basetype) in ('varchar','nvarchar'))
  25940.             select @pstrout = N'''' + REPLACE(CAST(@ssvar as nvarchar(4000)), '''', '''''') + N''''
  25941.         else if (lower(@basetype) in ('char','nchar'))
  25942.             select @pstrout = N'''' + REPLACE(RTRIM(CAST(@ssvar as nvarchar(4000))), '''', '''''') + N''''
  25943.         else if (lower(@basetype) in ('binary','varbinary'))
  25944.             select @pstrout = master.dbo.fn_varbintohexsubstring(1, CAST(@ssvar as varbinary(8000)), 1, 0)
  25945.         else if (lower(@basetype) in ('bit','bigint','int','smallint','tinyint','float','real','decimal','numeric'))
  25946.             select @pstrout = CAST(@ssvar as nvarchar(40))
  25947.         else if (lower(@basetype) in ('money','smallmoney'))
  25948.             select @pstrout = CONVERT(nvarchar(40), @ssvar, 2)
  25949.         else if (lower(@basetype) = 'uniqueidentifier')
  25950.             select @pstrout = N'''' + CAST(@ssvar as nvarchar(40)) + N''''
  25951.         else if (lower(@basetype) in ('datetime','smalldatetime'))
  25952.             select @pstrout = N'''' + CONVERT(nvarchar(40), @ssvar, 121) + N''''
  25953.         else
  25954.             select @pstrout = N'''Invalid Datatype' + lower(@basetype) + N'(' + CAST(@ssvar as nvarchar) + N')'''
  25955.     end
  25956.  
  25957.     -- All done
  25958.     return @pstrout
  25959. end
  25960. go
  25961. exec dbo.sp_MS_marksystemobject fn_sqlvarbasetostr
  25962. go
  25963.  
  25964. --
  25965. -- sp_replqueuemonitor
  25966. --
  25967. -- Description: this stored procedure displays the messages stored in the 
  25968. --      queue for a given subscription to a queued publication
  25969. --
  25970. -- Parameters:  
  25971. --    1. publisher (sysname, NULL for all publishers)
  25972. --    2. publisherdb (sysname, NULL for all publisherdbs)
  25973. --    3. publication (sysname , NULL for all publications)
  25974. --    4. tranid ( nvarchar(70) NULL for all transactions)
  25975. --      5. queuetype (tinyint 0 for all types of queues, 1 for MSMQ, 2 for SQL)
  25976. --
  25977. -- Results:
  25978. --  Rows of Messages stored in the queue (all types) in the following format:
  25979. --    publisher         sysname,
  25980. --    publisher_db     sysname,
  25981. --    publication     sysname,
  25982. --    tranid             sysname,
  25983. --    commandlen         int,
  25984. --    command         nvarchar(4000)
  25985. -- The command is truncated (less than 4000 characters) if
  25986. --    1. The total rowsize exceeds the maximum of 8060 bytes
  25987. --    2. The SQL command spans multiple queue messages
  25988. -- The queue messages that do not contain SQL command or are part of a spanning
  25989. -- SQL command are not displayed
  25990. --
  25991. -- Returns:
  25992. --         0 if success
  25993. --        1 if failure
  25994. --
  25995. raiserror('Creating procedure sp_replqueuemonitor', 0,1)
  25996. go
  25997. create proc sp_replqueuemonitor (
  25998.     @publisher         sysname = NULL
  25999.     ,@publisherdb     sysname = NULL
  26000.     ,@publication     sysname = NULL
  26001.     ,@tranid             sysname = NULL
  26002.     ,@queuetype        tinyint = 0    -- 0 = All Queues, 1 = MSMQ, 2 = SQL
  26003. )
  26004. as
  26005. begin
  26006.     set nocount on
  26007.     declare @retcode int
  26008.             ,@distributorprefix sysname
  26009.             ,@queue_id sysname
  26010.             ,@data varbinary(8000)
  26011.             ,@datalen int
  26012.             ,@commandtype int
  26013.             ,@cmdstate bit
  26014.             ,@mesglen int
  26015.             ,@command nvarchar(4000)
  26016.             ,@partialindex int
  26017.             ,@rowlen int
  26018.             ,@comandlen int
  26019.  
  26020.     declare    @k_mesg_partial_state bit
  26021.             ,@k_mesg_complete_state bit
  26022.             ,@k_mesg_tran_cmd int
  26023.             ,@k_max_rowlen int
  26024.             ,@k_queuetype_all tinyint
  26025.             ,@k_queuetype_msmq tinyint
  26026.             ,@k_queuetype_sql tinyint
  26027.  
  26028.     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, 
  26029.                             tranid sysname collate database_default, commandlen int, command ntext)
  26030.  
  26031.     --
  26032.     -- Check if need to look for subscriptions
  26033.     --
  26034.     if exists (select * from dbo.sysobjects where name = 'MSsubscription_agents')
  26035.     begin
  26036.         --
  26037.         -- Are there any qualifying subscriptions
  26038.         --
  26039.         if exists (select * from dbo.MSsubscription_agents where
  26040.                 publisher = case when @publisher is NULL then publisher else UPPER(@publisher) end AND
  26041.                 publisher_db = case when @publisherdb is NULL then publisher_db else @publisherdb end AND
  26042.                 publication = case when @publication is NULL then publication else @publication end )
  26043.         begin
  26044.             --
  26045.             -- initialize
  26046.             --
  26047.             select     @k_queuetype_all = 0
  26048.                     ,@k_queuetype_msmq = 1
  26049.                     ,@k_queuetype_sql = 2
  26050.                     
  26051.             --
  26052.             -- MSMQ based
  26053.             --
  26054.             if (@queuetype in (@k_queuetype_all, @k_queuetype_msmq) and
  26055.                 exists (select * from dbo.MSsubscription_agents where
  26056.                     publisher = case when @publisher is NULL then publisher else UPPER(@publisher) end AND
  26057.                     publisher_db = case when @publisherdb is NULL then publisher_db else @publisherdb end AND
  26058.                     publication = case when @publication is NULL then publication else @publication end  AND
  26059.                     update_mode IN (2,3) AND
  26060.                     queue_id != N'mssqlqueue'))
  26061.             begin
  26062.                 --
  26063.                 -- enumerate each queue
  26064.                 --
  26065.                 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)
  26066.                 declare #htempcursor cursor local for
  26067.                     select publisher, publisher_db, publication, queue_id 
  26068.                     from dbo.MSsubscription_agents 
  26069.                     where
  26070.                         publisher = case when @publisher is NULL then publisher else UPPER(@publisher) end AND
  26071.                         publisher_db = case when @publisherdb is NULL then publisher_db else @publisherdb end AND
  26072.                         publication = case when @publication is NULL then publication else @publication end  AND
  26073.                         update_mode IN (2,3) AND
  26074.                         queue_id != N'mssqlqueue'
  26075.  
  26076.                 open #htempcursor
  26077.                 fetch #htempcursor into @publisher, @publisherdb, @publication, @queue_id
  26078.                 while (@@fetch_status = 0)
  26079.                 begin
  26080.                     --
  26081.                     -- add the distributor prefix
  26082.                     --
  26083.                     select @distributorprefix = ISNULL(distributor, @@servername)
  26084.                     from dbo.MSsubscription_properties
  26085.                     where UPPER(publisher) = UPPER(@publisher) and
  26086.                             publisher_db = @publisherdb and
  26087.                             publication = @publication    
  26088.  
  26089.                     --
  26090.                     -- the server is a named instance, for MSMQ, just use SERVER MACHINE prefix
  26091.                     --
  26092.                     if (charindex(N'\', @distributorprefix) > 0)
  26093.                         select @distributorprefix = substring(@distributorprefix, 1, charindex(N'\', @distributorprefix) - 1)
  26094.                     select @distributorprefix = N'DIRECT=OS:' + @distributorprefix + N'\PRIVATE$\'
  26095.                     select @queue_id = @distributorprefix + @queue_id
  26096.                     
  26097.                     --
  26098.                     -- Display all the messages in this queue
  26099.                     --
  26100.                     insert into #mesgs (publisher, publisher_db, publication, tranid, commandlen, command)
  26101.                         exec @retcode = master.dbo.xp_displayqueuemesgs @publisher, @publisherdb, @publication, @queue_id, @tranid
  26102.                     if (@retcode != 0 or @@error != 0)
  26103.                         return 1
  26104.  
  26105.                     --
  26106.                     -- fetch next row
  26107.                     --
  26108.                     fetch #htempcursor into @publisher, @publisherdb, @publication, @queue_id
  26109.                 end
  26110.                 close #htempcursor
  26111.                 deallocate #htempcursor
  26112.     
  26113.                 --
  26114.                 -- All MSMQ Queues processed
  26115.                 --
  26116.                 drop table #queues
  26117.             end
  26118.             
  26119.             --
  26120.             -- SQL Queued based
  26121.             --
  26122.             if (@queuetype in (@k_queuetype_all, @k_queuetype_sql) and
  26123.                 exists (select * from dbo.MSsubscription_agents where
  26124.                     publisher = case when @publisher is NULL then publisher else UPPER(@publisher) end AND
  26125.                     publisher_db = case when @publisherdb is NULL then publisher_db else @publisherdb end AND
  26126.                     publication = case when @publication is NULL then publication else @publication end  AND
  26127.                     update_mode IN (4,5) AND
  26128.                     queue_id = N'mssqlqueue'))
  26129.             begin
  26130.                 --
  26131.                 -- check if we have a queue
  26132.                 --
  26133.                 if exists (select * from dbo.sysobjects where name = 'MSreplication_queue')
  26134.                 begin
  26135.                     --
  26136.                     -- initialize
  26137.                     --
  26138.                     select @mesglen = 0
  26139.                             ,@partialindex = 0
  26140.                             ,@k_mesg_partial_state = 1
  26141.                             ,@k_mesg_complete_state = 0
  26142.                             ,@k_mesg_tran_cmd = 1
  26143.                             ,@k_max_rowlen = 8000
  26144.                     
  26145.                     --
  26146.                     -- select the messages that qualify
  26147.                     --
  26148.                                             
  26149.                     declare #htempcursor cursor local for
  26150.                         select publisher, publisher_db, publication, tranid, datalen, data, commandtype, cmdstate
  26151.                         from dbo.MSreplication_queue 
  26152.                         where
  26153.                             publisher = case when @publisher is NULL then publisher else UPPER(@publisher) end AND
  26154.                             publisher_db = case when @publisherdb is NULL then publisher_db else @publisherdb end AND
  26155.                             publication = case when @publication is NULL then publication else @publication end  AND
  26156.                             tranid = case when @tranid IS NULL then tranid else @tranid end
  26157.                     open #htempcursor
  26158.                     fetch #htempcursor into @publisher, @publisherdb, @publication, @tranid, @datalen, @data, @commandtype, @cmdstate
  26159.                     while (@@fetch_status = 0)
  26160.                     begin
  26161.                         --
  26162.                         -- check the message state
  26163.                         --
  26164.                         if (@cmdstate = @k_mesg_partial_state)
  26165.                             select @partialindex = @partialindex + 1
  26166.                         select @mesglen = @mesglen + @datalen
  26167.  
  26168.                         --
  26169.                         -- process the body only for command type messages
  26170.                         -- and if the command spans multiple rows, then
  26171.                         -- display only the first row
  26172.                         --
  26173.                         if ((@commandtype = @k_mesg_tran_cmd) and
  26174.                             ((@cmdstate = @k_mesg_complete_state and @partialindex = 0) or
  26175.                             (@cmdstate = @k_mesg_partial_state and @partialindex = 1)))
  26176.                         begin
  26177.                             --
  26178.                             -- decode the command
  26179.                             --
  26180.                             exec @retcode = master.dbo.xp_decodequeuecmd @data, @command OUTPUT
  26181.                             if (@retcode != 0 or @@error != 0)
  26182.                                 return 1
  26183.                         end
  26184.                         
  26185.                         --
  26186.                         -- Are processing the final row for this command
  26187.                         --
  26188.                         if (@cmdstate = @k_mesg_complete_state)
  26189.                         begin
  26190.                             --
  26191.                             -- reset partial index
  26192.                             --
  26193.                             if (@partialindex > 0)
  26194.                                 select @partialindex = 0
  26195.  
  26196.                             if (@command IS NOT NULL)
  26197.                             begin
  26198.                                 --
  26199.                                 -- check if the command needs to truncated to fit the max rowsize
  26200.                                 --
  26201.                                 select @rowlen = 4 + DATALENGTH(@k_queuetype_sql) + 
  26202.                                                  DATALENGTH(@publisher) + DATALENGTH(@publisherdb) +
  26203.                                                  DATALENGTH(@publication) + DATALENGTH(@tranid) + 
  26204.                                                  DATALENGTH(@mesglen)
  26205.                                         ,@comandlen = DATALENGTH(@command)
  26206.                                 if (@rowlen + @comandlen > @k_max_rowlen)
  26207.                                 begin
  26208.                                     select @comandlen = @k_max_rowlen - @rowlen
  26209.                                     select @comandlen = @comandlen / 2
  26210.                                     select @command = SUBSTRING(@command, 1, @comandlen)
  26211.                                 end
  26212.                                 
  26213.                                 insert into #mesgs (queuetype, publisher, publisher_db, publication, tranid, commandlen, command)
  26214.                                 values (@k_queuetype_sql, @publisher, @publisherdb, @publication, @tranid, @mesglen, @command)
  26215.                                 if (@retcode != 0 or @@error != 0)
  26216.                                     return 1
  26217.  
  26218.                                 select @command = NULL
  26219.                             end
  26220.  
  26221.                             --
  26222.                             -- reset command len
  26223.                             --
  26224.                             if (@mesglen > 0)
  26225.                                 select @mesglen = 0
  26226.                         end
  26227.                         
  26228.                         --
  26229.                         -- fetch next row
  26230.                         --
  26231.                         fetch #htempcursor into @publisher, @publisherdb, @publication, @tranid, @datalen, @data, @commandtype, @cmdstate
  26232.                     end
  26233.                     close #htempcursor
  26234.                     deallocate #htempcursor
  26235.                 end 
  26236.     
  26237.                 --
  26238.                 -- All SQL Queues processed
  26239.                 --
  26240.             end
  26241.         end
  26242.     end
  26243.     
  26244.     --
  26245.     -- return result
  26246.     --
  26247.     select     queue = case when queuetype = @k_queuetype_msmq then N'MSMQ'
  26248.                         when queuetype = @k_queuetype_sql then N'SQLQ' end 
  26249.             ,publisher
  26250.             ,publisher_db
  26251.             ,publication
  26252.             ,tranid
  26253.             ,commandlen
  26254.             ,command 
  26255.     from #mesgs
  26256.     order by mesgid
  26257.     
  26258.     --
  26259.     -- All done
  26260.     --
  26261.     drop table #mesgs
  26262.     return 0
  26263. end
  26264. go
  26265. exec dbo.sp_MS_marksystemobject sp_replqueuemonitor
  26266. go
  26267.  
  26268. --
  26269. -- sp_replsqlqgetrows
  26270. --
  26271. -- Description: this stored procedure returns the queued data stored in the 
  26272. --     MSreplication_queue for a specific subscription to a queued publication.
  26273. --    This SP is used by Queue Reader Agent to service SQL based Queues.
  26274. --
  26275. -- Parameters:  
  26276. --    1. publisher         (sysname, NOT NULL)
  26277. --    2. publisherdb     (sysname, NOT NULL)
  26278. --    3. publication     (sysname, NOT NULL)
  26279. --
  26280. -- Results:
  26281. --  Rows of Queued Data stored in MSreplication_queue in the following format:
  26282. --    tranid                sysname
  26283. --    datalen                int
  26284. --    data                image
  26285. --    commandtype            int
  26286. --    insertdate            datetime
  26287. --    orderkey            bigint
  26288. --    cmdstate            bit
  26289. --
  26290. -- Returns:
  26291. --         0 if success
  26292. --        1 if failure
  26293. --
  26294. raiserror('Creating procedure sp_replsqlqgetrows', 0,1)
  26295. go
  26296. create proc sp_replsqlqgetrows (
  26297.     @publisher         sysname
  26298.     ,@publisherdb     sysname
  26299.     ,@publication     sysname
  26300. )
  26301. as
  26302. begin
  26303.     set nocount on
  26304.     
  26305.     --
  26306.     -- return rows
  26307.     --
  26308.     if exists (select * from dbo.sysobjects where name = 'MSreplication_queue')
  26309.     begin
  26310.         select tranid, datalen, data, commandtype, insertdate, orderkey, cmdstate 
  26311.         from dbo.MSreplication_queue with (READPAST) 
  26312.         where UPPER(publisher) = UPPER(@publisher) 
  26313.             and publisher_db = @publisherdb 
  26314.             and publication = @publication
  26315.         order by orderkey, tranid 
  26316.  
  26317.         if (@@error != 0)
  26318.             return 1
  26319.     end
  26320.     else
  26321.     begin
  26322.         --
  26323.         -- create empty rowset
  26324.         --
  26325.         declare @nomesgs TABLE (tranid     sysname, datalen int, data varbinary(8000),
  26326.             commandtype int, insertdate datetime, orderkey bigint, cmdstate bit)
  26327.         select * from @nomesgs
  26328.     end
  26329.     
  26330.     --
  26331.     -- All done
  26332.     --
  26333.     return 0
  26334. end
  26335. go
  26336. exec dbo.sp_MS_marksystemobject sp_replsqlqgetrows
  26337. go
  26338. --
  26339. -- sp_MSpost_auto_proc
  26340. --
  26341. -- Description: Helper store proc, used by schema replication.
  26342. --        Scripts out custom proc generation code and post to the log.
  26343. --
  26344. -- Returns:
  26345. --         0 if success
  26346. --        1 if failure
  26347. --
  26348. raiserror('Creating procedure sp_MSpost_auto_proc', 0,1)
  26349. go
  26350. create proc sp_MSpost_auto_proc 
  26351.         @pubid int, 
  26352.         @artid int, 
  26353.         @procname nvarchar(128)
  26354. as
  26355. begin
  26356.     declare @proctext nvarchar(4000)
  26357.     declare @retcode int
  26358.     
  26359.     set nocount on
  26360.     select @retcode = 0
  26361.     
  26362.     /*
  26363.     ** Security Check
  26364.     */
  26365.     exec @retcode = dbo.sp_MSreplcheck_publish
  26366.     if @@ERROR <> 0 or @retcode <> 0
  26367.         return(1)
  26368.  
  26369.     -- save the geneartion code
  26370.     create table #temptext (colidx int identity, col nvarchar(4000) collate database_default)
  26371.     insert #temptext (col) exec @procname @artid
  26372.     
  26373.     -- post to the log
  26374.     declare #trancolumn CURSOR LOCAL FAST_FORWARD for 
  26375.         select col from #temptext order by colidx
  26376.     open #trancolumn
  26377.     fetch #trancolumn into @proctext
  26378.     while (@@fetch_status <> -1)
  26379.     BEGIN
  26380.         if(@proctext = N'go') -- post the drop as one command
  26381.         begin
  26382.             exec @retcode = sp_replpostcmd 0, @pubid, @artid, 35, N' -- '
  26383.             if(@retcode <> 0) or (@@error <> 0)
  26384.                 return 1
  26385.         end
  26386.         else
  26387.         begin
  26388.             select @proctext = @proctext + N' '
  26389.             exec @retcode = sp_replpostcmd 1, @pubid, @artid, 35, @proctext
  26390.             if(@retcode <> 0) or (@@error <> 0)
  26391.                 return 1
  26392.         end
  26393.         fetch #trancolumn into @proctext
  26394.     END
  26395.     exec @retcode = sp_replpostcmd 0, @pubid, @artid, 35, N' --'
  26396.     if(@retcode <> 0) or (@@error <> 0)
  26397.         return 1
  26398.     close #trancolumn
  26399.     deallocate #trancolumn
  26400.     return 0
  26401. end
  26402. go
  26403. EXEC dbo.sp_MS_marksystemobject sp_MSpost_auto_proc
  26404. go
  26405. --
  26406. -- sp_MSrepl_schema 
  26407. --
  26408. -- Description: Helper store proc, used by schema replication.
  26409. --        constructs schema modification code and post to the log.
  26410. --
  26411. -- Returns:
  26412. --         0 if success
  26413. --        1 if failure
  26414. --
  26415. raiserror('Creating procedure sp_MSrepl_schema', 0,1)
  26416. go
  26417.  
  26418. create proc sp_MSrepl_schema @pubname sysname
  26419.                 ,@artid int 
  26420.                 ,@qual_source_object nvarchar(362) -- quoted table name
  26421.                 ,@column sysname -- column name, not quoted, as we need to search in syscolumns by it.
  26422.                 ,@operation int -- 0 is add, 1 is drop
  26423.                 ,@typetext nvarchar(3000) = NULL    
  26424.                 ,@schema_change_script nvarchar(4000) = NULL
  26425. as
  26426. begin
  26427.     declare @retcode int
  26428.     declare @pubid int
  26429.     declare @objid int
  26430.     declare @schema_option binary(8)
  26431.     declare @auto_gen int
  26432.     declare @cmd_type int
  26433.     declare @ins_cmd nvarchar(510)
  26434.     declare @del_cmd nvarchar(510)
  26435.     declare @upd_cmd nvarchar(510)
  26436.     declare @repub_command nvarchar(4000)
  26437.     declare @nopub_command nvarchar(4000)
  26438.     declare @prefix nvarchar(32)
  26439.     declare @post_cmd nvarchar(4000)
  26440.     declare @qual_column sysname
  26441.     declare @use_script bit
  26442.     declare @allow_dts bit
  26443.     
  26444.     set nocount on
  26445.     select @retcode = 0
  26446.     select @auto_gen = 2 -- auto generate custom procs
  26447.     select @cmd_type = 35 -- SQL statement
  26448.     select @qual_column = QUOTENAME(@column)
  26449.     select @objid = object_id(@qual_source_object)
  26450.  
  26451.     /*
  26452.     ** Security Check
  26453.     */
  26454.     exec @retcode = dbo.sp_MSreplcheck_publish
  26455.     if @@ERROR <> 0 or @retcode <> 0
  26456.         return(1)
  26457.  
  26458.     if (@schema_change_script is not NULL) and (len(@schema_change_script) > 0)
  26459.         select @use_script = 1
  26460.     else
  26461.         select @use_script = 0
  26462.     
  26463.     
  26464.     select @pubid = a.pubid, @schema_option = schema_option, @ins_cmd = ins_cmd, @del_cmd = del_cmd, @upd_cmd = upd_cmd, @allow_dts = allow_dts 
  26465.         from sysarticles a join syspublications p on a.pubid = p.pubid where artid = @artid
  26466.     
  26467.     if (@allow_dts = 1)
  26468.         goto SCRIPTONLY
  26469.  
  26470.     if(@operation = 0)
  26471.     begin
  26472.         select @repub_command = N'exec sp_repladdcolumn @source_object=N''' + @qual_source_object + N''',@column=N''' + replace(@column  , N'''', N'''''')
  26473.                         + N''',@typetext=N''' + replace(@typetext, N'''', N'''''') + N''' '
  26474.         select @nopub_command = N'else alter table ' + @qual_source_object + N' add ' + @qual_column + N' ' + @typetext + N' ' 
  26475.         select @prefix = N'if not exists '
  26476.     end
  26477.     else
  26478.     begin
  26479.         select @repub_command = N'exec sp_repldropcolumn @source_object=N''' + @qual_source_object + N''',@column=N''' + @column  + N''' '
  26480.         select @nopub_command = N'else alter table ' + @qual_source_object + N' drop column ' + @qual_column + N' '
  26481.         select @prefix = N'if exists '
  26482.     end
  26483.     if (@use_script = 1)--Need to pass the script file along if sub is republished.
  26484.         select @repub_command = @repub_command  + N',@schema_change_script=N''' + @schema_change_script + N''' '
  26485.     select @post_cmd = @prefix + N'(select * from syscolumns where name=N''' + @column + N''' and id = object_id('''+ @qual_source_object + N''')) begin '
  26486.     exec @retcode = sp_replpostcmd 1, @pubid, @artid, @cmd_type, @post_cmd 
  26487.     if(@retcode <> 0) or (@@error <> 0)
  26488.         return 1
  26489.     select @post_cmd = N'if exists (select * from sysobjects where name=N''syspublications'') if exists (select * from sysarticles where objid=object_id('''+ @qual_source_object + N''')) '
  26490.     exec @retcode = sp_replpostcmd 1, @pubid, @artid, @cmd_type, @post_cmd 
  26491.     if(@retcode <> 0) or (@@error <> 0)
  26492.         return 1
  26493.     exec @retcode = sp_replpostcmd 1, @pubid, @artid, @cmd_type, @repub_command
  26494.     if(@retcode <> 0) or (@@error <> 0)
  26495.         return 1
  26496.     exec @retcode = sp_replpostcmd 1, @pubid, @artid, @cmd_type, @nopub_command
  26497.     if(@retcode <> 0) or (@@error <> 0)
  26498.         return 1
  26499.     exec @retcode = sp_replpostcmd 1, @pubid, @artid, @cmd_type, @nopub_command
  26500.     if(@retcode <> 0) or (@@error <> 0)
  26501.         return 1
  26502.     exec @retcode = sp_replpostcmd 0, @pubid, @artid, @cmd_type, N' end '
  26503.     if(@retcode <> 0) or (@@error <> 0)
  26504.         return 1
  26505.     
  26506.     if ((convert(int, @schema_option) & @auto_gen) > 0)-- No script, but custom procs were auto-generated
  26507.     begin
  26508.         if(UPPER(LEFT(LTRIM(@ins_cmd), 4)) = UPPER('CALL'))
  26509.         begin
  26510.             exec @retcode = sp_MSpost_auto_proc @pubid, @artid, 'sp_scriptinsproc' 
  26511.             if(@retcode <> 0) or (@@error <> 0)
  26512.                 return 1
  26513.         end
  26514.         if(UPPER(LEFT(LTRIM(@del_cmd), 4)) = UPPER('CALL'))
  26515.         begin
  26516.             exec @retcode = sp_MSpost_auto_proc @pubid, @artid, 'sp_scriptdelproc' 
  26517.             if(@retcode <> 0) or (@@error <> 0)
  26518.                 return 1
  26519.         end
  26520.         else if(UPPER(LEFT(LTRIM(@del_cmd), 5)) = UPPER('XCALL'))
  26521.         begin
  26522.             exec @retcode = sp_MSpost_auto_proc @pubid, @artid, 'sp_scriptxdelproc' 
  26523.             if(@retcode <> 0) or (@@error <> 0)
  26524.                 return 1
  26525.         end
  26526.         if(UPPER(LEFT(LTRIM(@upd_cmd), 4)) = UPPER('CALL'))
  26527.         begin
  26528.             exec @retcode = sp_MSpost_auto_proc @pubid, @artid, 'sp_scriptupdproc' 
  26529.             if(@retcode <> 0) or (@@error <> 0)
  26530.                 return 1
  26531.         end
  26532.         else if(UPPER(LEFT(LTRIM(@upd_cmd), 5)) = UPPER('MCALL'))
  26533.         begin
  26534.             exec @retcode = sp_MSpost_auto_proc @pubid, @artid, 'sp_scriptmappedupdproc' 
  26535.             if(@retcode <> 0) or (@@error <> 0)
  26536.                 return 1
  26537.         end
  26538.         else if(UPPER(LEFT(LTRIM(@upd_cmd), 5)) = UPPER('XCALL'))
  26539.         begin
  26540.             exec @retcode = sp_MSpost_auto_proc @pubid, @artid, 'sp_scriptxupdproc' 
  26541.             if(@retcode <> 0) or (@@error <> 0)
  26542.                 return 1
  26543.         end
  26544.     end
  26545. SCRIPTONLY:
  26546.  
  26547.     if (@use_script = 1)
  26548.     begin
  26549.         exec @retcode = sp_addscriptexec @publication = @pubname, @scriptfile = @schema_change_script
  26550.         if @retcode<>0 or @@ERROR<>0
  26551.             return 1
  26552.     end 
  26553.     return 0
  26554. end
  26555. go
  26556. EXEC dbo.sp_MS_marksystemobject sp_MSrepl_schema 
  26557. go
  26558. --
  26559. -- sp_MSreplupdateschema
  26560. --
  26561. -- Description: Wrapper store proc, check for admin\dbowner credential before invoking sp_replupdateschema
  26562. --
  26563. -- Returns:
  26564. --         0 if success
  26565. --        1 if failure
  26566. --
  26567. raiserror('Creating procedure sp_MSreplupdateschema', 0,1)
  26568. go
  26569.  
  26570. create proc sp_MSreplupdateschema  @object_name sysname
  26571. as
  26572. begin
  26573.     declare @retcode int
  26574.     IF @object_name IS NULL
  26575.     BEGIN
  26576.         RAISERROR (14043, 16, -1, '@object_name')
  26577.         RETURN (1)
  26578.     END
  26579.  
  26580.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  26581.     IF @@ERROR <> 0 or @retcode <> 0
  26582.             return (1)
  26583.  
  26584.     exec dbo.sp_replupdateschema @object_name
  26585.     return 0
  26586. end
  26587. go
  26588. EXEC dbo.sp_MS_marksystemobject sp_MSreplupdateschema
  26589. go
  26590. --
  26591. -- sp_MSdefer_check
  26592. --
  26593. -- Description: disable constraints (Foreign Key and Check) and triggers during concurrent snapshot
  26594. --        and script enable cmds for later
  26595. --
  26596. -- Note:     this stored procedure loops through the list of Foreign Key, Check constraints and Triggers
  26597. --        which are not disabled and not marked 'not for replicaiton', it uses 'alter table' to disable 
  26598. --        these entries (nocheck/disable), and copies the corresponding enable code into a temp table.
  26599. --        at the end, cmds in temp table is used to build a stored procedure which will be used by dist 
  26600. --        agent to enable these cnst/triggers at the end of concurrent snapshot. if it failed to create 
  26601. --        the stored procedure, a default one (sp_MSreenable_check) will be used, the key difference here
  26602. --        is the sp created here will only enable the ones we disabled here, while the default one will 
  26603. --        enable all in current table.
  26604. --
  26605. --        the sp created within sp_MSdefer_check will enable all the entries disabled by sp_MSdefer_check, 
  26606. --        then drop itself at the end.
  26607. --
  26608. -- Returns:
  26609. --         0 if success
  26610. --        1 if failure
  26611. --
  26612. raiserror('Creating procedure sp_MSdefer_check', 0,1)
  26613. go
  26614. create proc sp_MSdefer_check @objname sysname, @objowner sysname = NULL
  26615. as
  26616.     set nocount on
  26617.     declare @cnstname sysname
  26618.     declare @cnstid int
  26619.     declare @objid int
  26620.     declare @enable_cmd nvarchar(4000)
  26621.     declare @disable_cmd nvarchar(4000)
  26622.     declare @quotedproc nvarchar(240)
  26623.     declare @dest nvarchar(514)
  26624.     declare @dbname sysname
  26625.     declare @proc_exists bit
  26626.  
  26627.     if(@objowner is not null)
  26628.         select @dest = quotename(@objowner) + N'.' + quotename(@objname)
  26629.     else
  26630.         select @dest = quotename(@objname)
  26631.  
  26632.     declare @retcode int
  26633.     IF @objname IS NULL
  26634.     BEGIN
  26635.         RAISERROR (14043, 16, -1, '@objname')
  26636.         RETURN (1)
  26637.     END
  26638.  
  26639.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  26640.     IF @@ERROR <> 0 or @retcode <> 0
  26641.             return (1)
  26642.  
  26643.     select @objid = object_id(@dest)
  26644.     select @enable_cmd = N'sp_MSenable_' + convert(varchar(64), @objid)
  26645.     if exists(select name from sysobjects where name = @enable_cmd and ObjectProperty(id, 'IsProcedure') = 1)
  26646.         select @proc_exists = 1
  26647.     else
  26648.         select @proc_exists = 0
  26649.  
  26650.     select @quotedproc = quotename(@enable_cmd)
  26651.     select @enable_cmd = N'create proc ' + @quotedproc + N' as '
  26652.     create table ##proccmd (c1 int identity, c2 nvarchar(3000) collate database_default)
  26653.     insert ##proccmd (c2) values (@enable_cmd)
  26654.     
  26655.     declare ms_crs_cnst cursor local static for
  26656.     select name, id from sysobjects where parent_obj = @objid and 
  26657.            ((OBJECTPROPERTY(id, 'CnstIsDisabled') = 0 and OBJECTPROPERTY(id, 'CnstIsNotRepl') = 0 and 
  26658.             (OBJECTPROPERTY(id, 'IsCheckCnst') = 1 or OBJECTPROPERTY(id, 'IsForeignKey') = 1))
  26659.         or (ObjectProperty(id, 'IsTrigger') = 1 and OBJECTPROPERTY(id, 'ExecIsTriggerNotForRepl') = 0 and ObjectProperty(id, 'ExecIsTriggerDisabled') = 0))
  26660.     for read only
  26661.  
  26662.     open ms_crs_cnst
  26663.     fetch ms_crs_cnst into @cnstname, @cnstid
  26664.     while @@fetch_status >= 0
  26665.     begin
  26666.         if(ObjectProperty(@cnstid, 'IsTrigger') = 1)
  26667.         begin
  26668.             select @disable_cmd = N'alter table ' + @dest + N' disable trigger ' + quotename(@cnstname)
  26669.             select @enable_cmd = N'alter table ' + @dest + N' enable trigger '+quotename(@cnstname)
  26670.         end
  26671.         else
  26672.         begin
  26673.             select @disable_cmd = N'alter table ' + @dest + N' nocheck constraint ' + quotename(@cnstname)
  26674.             select @enable_cmd = N'alter table ' + @dest + N' check constraint ' + quotename(@cnstname)
  26675.         end
  26676.         insert ##proccmd (c2) values (@enable_cmd)
  26677.  
  26678.         execute(@disable_cmd)
  26679.         fetch ms_crs_cnst into @cnstname, @cnstid
  26680.     end        --of major loop
  26681.     deallocate ms_crs_cnst
  26682.     if(@proc_exists = 1) -- don't try to recreate the proc
  26683.     begin 
  26684.         select N'exec ' + @quotedproc
  26685.         drop table ##proccmd
  26686.         return 0
  26687.     end
  26688.  
  26689.     select @enable_cmd = N'drop proc ' + @quotedproc
  26690.     insert ##proccmd (c2) values (@enable_cmd)
  26691.     select @enable_cmd = N'select c2 from ##proccmd order by c1'
  26692.     select @dbname = db_name()
  26693.     exec @retcode = master..xp_execresultset @enable_cmd, @dbname
  26694.     if @@error <> 0 or @retcode <> 0 or @quotedproc is NULL
  26695.     begin
  26696.         declare @cmd_param nvarchar(4000)
  26697.         if (@objowner is null)
  26698.             select @cmd_param = N' @objname = N''' + @objname + N''''
  26699.         else
  26700.             select @cmd_param = N' @objname = N''' + @objname + N''', @objowner = N''' + @objowner + N''''
  26701.         select N'exec sp_MSreenable_check ' + @cmd_param
  26702.     end
  26703.     else
  26704.         select N'exec ' + @quotedproc
  26705.     drop table ##proccmd
  26706.     return 0
  26707. go
  26708. EXEC dbo.sp_MS_marksystemobject sp_MSdefer_check
  26709. go
  26710. --
  26711. -- sp_MSreenable_check
  26712. --
  26713. -- Description: default sp to enable constraints (Foreign Key and Check) and triggers at 
  26714. --        the end of compensation mode in concurrent snapshot.
  26715. --
  26716. -- Note :     this default sp doesn't get used unless we failed to construct a temp one at runtime.
  26717. --
  26718. -- Returns:
  26719. --         0 if success
  26720. --        1 if failure
  26721. --
  26722. raiserror('Creating procedure sp_MSreenable_check', 0,1)
  26723. go
  26724. create proc sp_MSreenable_check @objname sysname, @objowner sysname = NULL
  26725. as
  26726.     set nocount on
  26727.     
  26728.     declare @cnstname sysname
  26729.     declare @cnstid int
  26730.     declare @objid int
  26731.     declare @enable_cmd nvarchar(4000)
  26732.     declare @dest nvarchar(514)
  26733.  
  26734.     declare @retcode int
  26735.     IF @objname IS NULL
  26736.     BEGIN
  26737.         RAISERROR (14043, 16, -1, '@objname')
  26738.         RETURN (1)
  26739.     END
  26740.  
  26741.     if(@objowner is not null)
  26742.         select @dest = quotename(@objowner) + N'.' + quotename(@objname)
  26743.     else
  26744.         select @dest = quotename(@objname)
  26745.  
  26746.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  26747.     IF @@ERROR <> 0 or @retcode <> 0
  26748.             return (1)
  26749.  
  26750.     select @objid = object_id(@objname)
  26751.     
  26752.     declare ms_crs_cnst cursor local static for
  26753.     select name, id from sysobjects where parent_obj = @objid and 
  26754.            ((OBJECTPROPERTY(id, 'CnstIsDisabled') = 1 and OBJECTPROPERTY(id, 'CnstIsNotRepl') = 0 and 
  26755.             (OBJECTPROPERTY(id, 'IsCheckCnst') = 1 or OBJECTPROPERTY(id, 'IsForeignKey') = 1))
  26756.         or (ObjectProperty(id, 'IsTrigger') = 1 and OBJECTPROPERTY(id, 'ExecIsTriggerNotForRepl') = 0 and ObjectProperty(id, 'ExecIsTriggerDisabled') = 1))
  26757.     for read only
  26758.  
  26759.     open ms_crs_cnst
  26760.     fetch ms_crs_cnst into @cnstname, @cnstid
  26761.     while @@fetch_status >= 0
  26762.     begin
  26763.         if(ObjectProperty(@cnstid, 'IsTrigger') = 1)
  26764.             select @enable_cmd = N'alter table ' + @dest + N' enable trigger ' + quotename(@cnstname)
  26765.         else
  26766.             select @enable_cmd = N'alter table ' + @dest + N' check constraint ' + quotename(@cnstname)
  26767.  
  26768.         execute(@enable_cmd)
  26769.         fetch ms_crs_cnst into @cnstname, @cnstid
  26770.     end        --of major loop
  26771.     deallocate ms_crs_cnst
  26772.     return 0
  26773. go
  26774. EXEC dbo.sp_MS_marksystemobject sp_MSreenable_check
  26775. go
  26776.  
  26777. --
  26778. -- sp_getqueuedrows
  26779. --
  26780. -- sp_getqueuedrows is invoked by user to find the rows of given table on
  26781. -- a subscriber database that have participated in a queued update and 
  26782. -- currently have not been resolved by the queue reader agent - i.e. current
  26783. -- have an outstanding queued transaction. The table has to be part of 
  26784. -- queued subscription.
  26785. -- 
  26786. -- Parameters
  26787. --     @tablename    sysname -- name of table
  26788. --    @user        sysname -- optional name of user
  26789. --    @tranid        nvarchar(70) -- optional tranid to filter results on
  26790. --
  26791. -- Returns
  26792. --    0 if success 
  26793. --    1 if failure
  26794. --
  26795. -- Resultset
  26796. --     Rows that currently have at least one queued transaction for this
  26797. --    subscribed table
  26798. --
  26799. raiserror('Creating procedure sp_getqueuedrows', 0,1)
  26800. go
  26801. create proc sp_getqueuedrows (
  26802.     @tablename sysname
  26803.     ,@owner sysname = NULL
  26804.     ,@tranid nvarchar(70) = NULL
  26805. )
  26806. as
  26807. begin
  26808.     set nocount on
  26809.     declare @retcode int
  26810.         ,@dbname sysname
  26811.         ,@qualified_tabname nvarchar(1000)
  26812.         ,@tabid int
  26813.         ,@agent_id int
  26814.         ,@publisher sysname
  26815.         ,@publisher_db sysname
  26816.         ,@publication sysname
  26817.         ,@queue_id sysname
  26818.         ,@update_mode int
  26819.         ,@failover_id int
  26820.         ,@cmd nvarchar(4000)
  26821.         ,@distributorprefix sysname
  26822.         ,@indid int
  26823.         ,@indkey int
  26824.         ,@key sysname
  26825.         ,@colid int
  26826.         ,@typestring nvarchar(4000)
  26827.         ,@artcol int
  26828.         ,@xpinputstr nvarchar(4000)
  26829.         ,@selectcl nvarchar(4000)
  26830.         ,@joincl nvarchar(4000)
  26831.  
  26832.     --
  26833.     -- prepare the fully qualified table
  26834.     --
  26835.     select @owner = case when (@owner IS NULL) then N'dbo' else @owner end
  26836.             ,@dbname = db_name()    
  26837.     select @qualified_tabname = quotename(@dbname) + N'.' 
  26838.                     + quotename(@owner) + N'.' + quotename(@tablename)
  26839.     select @tabid = object_id(@qualified_tabname)
  26840.     if (@tabid IS NULL) or (@tabid = 0)
  26841.     begin
  26842.         -- error
  26843.         raiserror('sp_getqueuedrows(debug): could not locate table %s', 16, 1, @qualified_tabname)
  26844.         return 1
  26845.     end
  26846.  
  26847.     --
  26848.     -- current user should have SELECT permission on the table
  26849.     --
  26850.     if ( permissions(@tabid) & 0x1 = 0 )
  26851.     begin
  26852.         -- error
  26853.         raiserror('sp_getqueuedrows(debug): current user does not have SELECT permission on table %s', 16, 1, @qualified_tabname)
  26854.         return 1
  26855.     end
  26856.  
  26857.     --
  26858.     -- make sure the table is participating in a active queued subscription
  26859.     --
  26860.     select @agent_id = agent_id 
  26861.     from dbo.MSsubscription_articles 
  26862.     where dest_table = @tablename and owner = @owner
  26863.  
  26864.     if (@agent_id IS NULL)
  26865.     begin
  26866.         -- error
  26867.         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)
  26868.         return 1
  26869.     end
  26870.  
  26871.     --
  26872.     -- get the details for the subscription
  26873.     --
  26874.     select @publisher = publisher
  26875.             ,@publisher_db = publisher_db
  26876.             ,@publication = publication
  26877.             ,@update_mode = update_mode
  26878.             ,@queue_id = queue_id
  26879.             ,@failover_id = failover_mode
  26880.     from dbo.MSsubscription_agents where id = @agent_id
  26881.     if (@update_mode not in (2,3,4,5))
  26882.     begin
  26883.         -- error
  26884.         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)
  26885.         return 1
  26886.     end
  26887.     
  26888.     --
  26889.     -- If we are in Immediate Failover mode - no queued messages
  26890.     --
  26891.     if (@update_mode in (3,5) and (@failover_id = 0))
  26892.     begin
  26893.         --
  26894.         -- do an empty select on the source table and return
  26895.         --
  26896.         select @cmd = N'declare @dummy_action nvarchar(10), @dummy_tranid nvarchar(70)
  26897.                     select action=@dummy_action, tranid=@dummy_tranid, * from ' + 
  26898.                     @qualified_tabname + N' where 1 = 2 '
  26899.         exec (@cmd)
  26900.         return 0
  26901.     end
  26902.  
  26903.     if (@update_mode in (2,3))
  26904.     begin
  26905.         --
  26906.         -- set queue prefix for MSMQ cases
  26907.         --
  26908.         select @distributorprefix = ISNULL(distributor, @@servername)
  26909.         from dbo.MSsubscription_properties
  26910.         where UPPER(publisher) = UPPER(@publisher) and
  26911.                 publisher_db = @publisher_db and
  26912.                 publication = @publication    
  26913.  
  26914.         --
  26915.         -- the server is a named instance, for MSMQ, just use SERVER MACHINE prefix
  26916.         --
  26917.         if (charindex(N'\', @distributorprefix) > 0)
  26918.             select @distributorprefix = substring(@distributorprefix, 1, charindex(N'\', @distributorprefix) - 1)
  26919.         select @distributorprefix = N'DIRECT=OS:' + @distributorprefix + N'\PRIVATE$\'
  26920.         select @queue_id = @distributorprefix + @queue_id
  26921.     end
  26922.     else
  26923.     begin
  26924.         --
  26925.         -- Check the queue table for SQLQ
  26926.         --
  26927.         if not exists (select * from dbo.MSreplication_queue
  26928.         where UPPER(publisher) = UPPER(@publisher) and
  26929.                 publisher_db = @publisher_db and
  26930.                 publication = @publication and
  26931.                 tranid = case when @tranid IS NULL then tranid else @tranid end)
  26932.         begin
  26933.             --
  26934.             -- do an empty select on the source table and return
  26935.             --
  26936.             select @cmd = N'declare @dummy_action nvarchar(10), @dummy_tranid nvarchar(70)
  26937.                     select action=@dummy_action, tranid=@dummy_tranid, * from ' + 
  26938.                     @qualified_tabname + N' where 1 = 2 '
  26939.             exec (@cmd)
  26940.             return 0
  26941.         end
  26942.     end
  26943.  
  26944.     --
  26945.     -- Now find the PK columns for this table
  26946.     --
  26947.     select @indkey = 1
  26948.         ,@artcol = 0
  26949.         ,@xpinputstr = N''
  26950.         ,@selectcl = N''
  26951.         ,@joincl = N''
  26952.         ,@retcode = 0
  26953.  
  26954.     select @indid = i.indid 
  26955.     from dbo.sysindexes i 
  26956.     where ((i.status & 2048) != 0) and (i.id = @tabid)
  26957.     if (@indid is null)
  26958.     begin
  26959.         raiserror('sp_getqueuedrows(debug): Cannot find primary key for %s', 
  26960.                 16, -1, @qualified_tabname)
  26961.         return 1
  26962.     end
  26963.     
  26964.     --
  26965.     -- create an enumeration of all the columns that are part of PK
  26966.     --
  26967.     create table #pkcoltab(pkindex int identity, keyname sysname collate database_default not null)
  26968.     while (@indkey <= 16)
  26969.     begin
  26970.         select @key = index_col( @qualified_tabname, @indid, @indkey )
  26971.         if (@key is null)
  26972.             break
  26973.         else
  26974.             insert into #pkcoltab(keyname) values(@key)
  26975.  
  26976.         select @indkey = @indkey + 1
  26977.     end
  26978.  
  26979.     --
  26980.     -- initialize the commands that we need to build
  26981.     --
  26982.     if exists (select * from dbo.sysobjects where name = 'tempcrtcmd')
  26983.         drop table tempcrtcmd
  26984.     create table tempcrtcmd (c1 int identity NOT NULL, procedure_text nvarchar(4000) NULL)
  26985.     
  26986.     select @cmd = N'create table tempqjointab (action nvarchar(10), tranid nvarchar(70) '
  26987.     insert into tempcrtcmd(procedure_text) values(@cmd)
  26988.  
  26989.     --
  26990.     -- now walk through each article col and if it is
  26991.     -- a part of PK, then check find the column position of the key
  26992.     -- corresponding to any article column is set
  26993.     --
  26994.     DECLARE #hCColid CURSOR LOCAL FAST_FORWARD FOR 
  26995.         select colid, [name] from dbo.syscolumns 
  26996.         where id = @tabid order by colid asc
  26997.  
  26998.     OPEN #hCColid
  26999.     FETCH #hCColid INTO @colid, @key
  27000.     WHILE (@@fetch_status != -1)
  27001.     begin
  27002.         exec sp_MSget_type @tabid, @colid, NULL, @typestring output
  27003.         if ((@typestring IS NOT NULL) and (@typestring != N'timestamp'))
  27004.         begin
  27005.             --
  27006.             -- this column is part of the article
  27007.             --
  27008.             select @artcol = @artcol + 1
  27009.             if exists (select * from #pkcoltab where keyname = @key)
  27010.             begin
  27011.                 --
  27012.                 -- this column is part of PK (offset and precision, scale)
  27013.                 -- prepare the input string for XP
  27014.                 -- prepare the create join table command
  27015.                 -- prepare the join and select clause for the result
  27016.                 --
  27017.                 select @xpinputstr = @xpinputstr + N';' + cast(@artcol as nvarchar) 
  27018.                 if (@typestring = N'bigint')
  27019.                     select @xpinputstr = @xpinputstr + N'(19,0)'
  27020.                 else if (@typestring like N'decimal%') or (@typestring like N'numeric%')
  27021.                 begin
  27022.                     declare @startpos int
  27023.                             ,@endpos  int
  27024.  
  27025.                     select @startpos = charindex(N'(', @typestring, 1)
  27026.                     select @endpos = charindex(N')', @typestring, @startpos)
  27027.                     select @xpinputstr = @xpinputstr + substring(@typestring, @startpos, (@endpos - @startpos + 1))
  27028.                 end
  27029.                 select @cmd = N',' + quotename(@key) + N' ' + @typestring
  27030.                 insert into tempcrtcmd(procedure_text) values(@cmd)
  27031.                 select @selectcl = @selectcl + N', b.' + quotename(@key)
  27032.                 
  27033.                 if (@artcol = 1)
  27034.                 begin
  27035.                     select @joincl = @joincl + N'a.' + quotename(@key) + N' = b.' + quotename(@key)
  27036.                 end
  27037.                 else
  27038.                 begin
  27039.                     select @joincl = @joincl + N'and a.' + quotename(@key) + N' = b.' + quotename(@key)
  27040.                 end                
  27041.             end
  27042.             else
  27043.             begin
  27044.                 --
  27045.                 -- this column is not part of PK
  27046.                 -- build the select clause for this column
  27047.                 --
  27048.                 select @selectcl = @selectcl + N', a.' + quotename(@key)
  27049.             end
  27050.         end        
  27051.  
  27052.         --
  27053.         -- get the next column
  27054.         --
  27055.         FETCH #hCColid INTO @colid, @key
  27056.     end
  27057.     CLOSE #hCColid
  27058.     DEALLOCATE #hCColid
  27059.     drop table #pkcoltab
  27060.  
  27061.     --
  27062.     -- create the join table now
  27063.     --
  27064.     select @cmd = N') '
  27065.     insert into tempcrtcmd(procedure_text) values(@cmd)
  27066.     if exists (select * from dbo.sysobjects where name = N'tempqjointab')
  27067.         drop table tempqjointab
  27068.     select @cmd = 'select procedure_text from dbo.tempcrtcmd order by c1'
  27069.     exec master..xp_execresultset @cmd, @dbname
  27070.  
  27071.     --
  27072.     -- populate the join table now
  27073.     --
  27074.     if (@update_mode in (2,3))
  27075.     begin
  27076.         --
  27077.         -- MSMQ case : one call to the xp should populate the join table
  27078.         --
  27079.         insert into tempqjointab
  27080.             exec master.dbo.xp_readpkfromqueue @tablename, @queue_id, @xpinputstr, @tranid
  27081.     end
  27082.     else
  27083.     begin
  27084.         --
  27085.         -- SQLQ case : select the data for this subscription and call the
  27086.         -- xp for each row in the cursor to populate the join table
  27087.         --
  27088.         declare @spancount int
  27089.                 ,@data varbinary(8000)
  27090.                 ,@state bit
  27091.         
  27092.         declare #hcurQInfo cursor local FAST_FORWARD FOR
  27093.         select data, cmdstate, tranid
  27094.         from dbo.MSreplication_queue
  27095.         where UPPER(publisher) = UPPER(@publisher) and
  27096.                 publisher_db = @publisher_db and
  27097.                 publication = @publication and
  27098.                 tranid = case when @tranid IS NULL then tranid else @tranid end and
  27099.                 commandtype = 1
  27100.         order by orderkey
  27101.         FOR READ ONLY
  27102.  
  27103.         select @spancount = 0
  27104.         open #hcurQInfo
  27105.         fetch #hcurQInfo into @data, @state, @tranid
  27106.         while (@@FETCH_STATUS = 0)
  27107.         begin
  27108.             declare @qbdata0 varbinary(8000)
  27109.                     ,@qbdata1 varbinary(8000)
  27110.  
  27111.             if (@state = 1)
  27112.             begin
  27113.                 --
  27114.                 -- command spanning more than a row
  27115.                 -- we will allow spanning upto 2 rows
  27116.                 --
  27117.                 if (@spancount = 0)
  27118.                     select @qbdata0 = @data
  27119.                 else
  27120.                 begin
  27121.                     raiserror('sp_getqueuedrows(debug): Queued data spans 3 rows, cannot proceed', 16, -1)
  27122.                     close #hcurQInfo
  27123.                     deallocate #hcurQInfo
  27124.                     select @retcode = 1
  27125.                     goto cleanup
  27126.                 end
  27127.                 select @spancount = @spancount + 1
  27128.             end
  27129.             else
  27130.             begin
  27131.                 --
  27132.                 -- final row for the command
  27133.                 --
  27134.                 if (@spancount = 0)
  27135.                     select @qbdata0 = @data                
  27136.                 else if (@spancount = 1)
  27137.                     select @qbdata1 = @data
  27138.                 else
  27139.                 begin
  27140.                     raiserror('sp_getqueuedrows(debug): Queued data spans 3 rows, cannot proceed', 16, -1)
  27141.                     close #hcurQInfo
  27142.                     deallocate #hcurQInfo
  27143.                     select @retcode = 1
  27144.                     goto cleanup
  27145.                 end
  27146.  
  27147.                 --
  27148.                 -- call the xp to populate the join table
  27149.                 --
  27150.                 insert into tempqjointab
  27151.                     exec master.dbo.xp_readpkfromvarbin @tablename, @xpinputstr, @tranid, @spancount, @qbdata0, @qbdata1
  27152.  
  27153.                 --
  27154.                 -- reset the span count
  27155.                 --
  27156.                 select @spancount = 0
  27157.             end
  27158.  
  27159.             --
  27160.             -- fetch the next row
  27161.             --
  27162.             fetch #hcurQInfo into @data, @state, @tranid
  27163.         end
  27164.         close #hcurQInfo
  27165.         deallocate #hcurQInfo
  27166.     end
  27167.  
  27168.     --
  27169.     -- Now perform the join
  27170.     --
  27171.     select @cmd = N'select b.action, b.tranid ' + @selectcl 
  27172.         + N'from ' + @qualified_tabname + N' a right join tempqjointab b on (' + @joincl + N') '
  27173.     exec (@cmd)
  27174.     
  27175.     --
  27176.     -- all done
  27177.     --
  27178. cleanup:    
  27179.     if exists (select * from dbo.sysobjects where name = N'tempqjointab')
  27180.         drop table tempqjointab
  27181.     if exists (select * from dbo.sysobjects where name = 'tempcrtcmd')
  27182.         drop table tempcrtcmd
  27183.     return @retcode
  27184. end
  27185. go
  27186.  
  27187. EXEC dbo.sp_MS_marksystemobject sp_getqueuedrows
  27188. GO
  27189. --
  27190. -- sp_MSprep_exclusive
  27191. --
  27192. -- Description: Helper sp for schema change, acquires shc-m lock on the source table, 
  27193. --        and 'Exclusive' application lock on all the publications it belongs to.
  27194. --
  27195. -- Note :     @objname should be owner qualified
  27196. -- Returns:
  27197. --         0 if success
  27198. --        1 if failure
  27199. --
  27200. raiserror('Creating procedure sp_MSprep_exclusive', 0,1)
  27201. go
  27202. create proc sp_MSprep_exclusive @objname sysname
  27203. as
  27204.     set nocount on
  27205.     declare @retcode int
  27206.     declare @objid int
  27207.     declare @tran_pubname sysname
  27208.  
  27209.     EXEC @retcode = dbo.sp_MSreplcheck_publish
  27210.     IF @@ERROR <> 0 or @retcode <> 0
  27211.         return (1)
  27212.  
  27213.     if @objname is NULL
  27214.     begin
  27215.         RAISERROR (14043, 16, -1, '@objname')
  27216.         return (1)
  27217.     end
  27218.  
  27219.     select @objid = object_id(@objname)
  27220.     if @objid is NULL
  27221.     begin
  27222.         raiserror(14027, 16, -1, @objname)
  27223.         return (1)
  27224.     end
  27225.  
  27226.     exec sp_replupdateschema @objname
  27227.     if @@ERROR<>0
  27228.         return (1)
  27229.  
  27230.     declare #trancolumn CURSOR LOCAL FAST_FORWARD for 
  27231.             select p.name from sysarticles a, syspublications p where a.objid=@objid
  27232.                     and p.pubid = a.pubid
  27233.     open #trancolumn
  27234.     fetch #trancolumn into @tran_pubname
  27235.     while (@@fetch_status <> -1)
  27236.     BEGIN
  27237.         EXEC @retcode = sp_getapplock     @Resource = @tran_pubname, 
  27238.                         @LockMode = N'Exclusive', 
  27239.                         @LockOwner = N'Transaction', 
  27240.                         @LockTimeout = 0
  27241.         if @retcode = -1
  27242.         begin 
  27243.             raiserror(21386, 16, -1, @objname)
  27244.             goto FAILURE    
  27245.         end 
  27246.         if @@ERROR<>0 or @retcode < 0
  27247.             goto FAILURE
  27248.         fetch #trancolumn into @tran_pubname            
  27249.     END
  27250.     close #trancolumn
  27251.     deallocate #trancolumn
  27252.     return 0
  27253. FAILURE:
  27254.     close #trancolumn
  27255.     deallocate #trancolumn
  27256.     return (1)
  27257. go
  27258. EXEC dbo.sp_MS_marksystemobject sp_MSprep_exclusive
  27259. --
  27260. -- sp_verify_publication
  27261. --
  27262. -- Description: Invoked by user on a distributor server to perform a simple replication plumbing check.
  27263. --        Tests the connectivity of all the push subscriptions for a given publication.
  27264. --        (doesn't test pull or anonymous subscriptions)
  27265. --
  27266. -- Returns:
  27267. --         0 if success
  27268. --        1 if failure
  27269. --
  27270. raiserror('Creating procedure sp_verify_publication', 0,1)
  27271. go
  27272. create proc sp_verify_publication (
  27273.     @publisher sysname,        /*name of the publisher*/
  27274.     @publisher_db sysname,        /*the database for the publication*/
  27275.     @publication sysname,        /*name of the publication*/
  27276.     @reserved int = 0        /*reserved -- should not be used directly by user.
  27277.                       For internal use only.*/
  27278. )
  27279. AS
  27280. BEGIN
  27281. set nocount on
  27282.  
  27283. if( @reserved = 0 )
  27284. begin
  27285.   declare @proc nvarchar(255),
  27286.       @distribution_db sysname,
  27287.       @recurse_retcode int
  27288.   --
  27289.   --verify that this server is a distributor.
  27290.   --
  27291.   if (not exists( select * from msdb..sysobjects where name = 'MSdistpublishers') )
  27292.   begin
  27293.     RAISERROR(14114, 16, -1, @@SERVERNAME)
  27294.     return(1)
  27295.   end
  27296.   --
  27297.   --get the distribution database
  27298.   --
  27299.   select @distribution_db = distribution_db from msdb.dbo.MSdistpublishers where UPPER(name) = UPPER(@publisher) collate database_default
  27300.   if( @distribution_db is NULL )
  27301.   begin
  27302.     RAISERROR(21169, 16, -1, @publisher, @@SERVERNAME, @publisher)
  27303.     return(1)
  27304.   end
  27305.  
  27306.   select @proc = @distribution_db + '.dbo.sp_verify_publication'
  27307.   exec @recurse_retcode = @proc @publisher, @publisher_db, @publication, 1
  27308.   return(@recurse_retcode)
  27309. end
  27310.  
  27311. declare @publisher_id smallint,
  27312.     @subscriber sysname,
  27313.     @subscriber_db sysname,
  27314.     @type tinyint,
  27315.     @job_id binary(16),
  27316.     @publication_type int,
  27317.     @agent_type varchar(15),
  27318.     @command nvarchar(3200),
  27319.     @success varchar(300),
  27320.     @srvid smallint
  27321.  
  27322. select @srvid = srvid from master.dbo.sysservers where UPPER(srvname) = UPPER(@publisher) collate database_default
  27323. if @srvid is NULL
  27324. begin
  27325.   RAISERROR(21169, 16, -1, @publisher, @@SERVERNAME, @publisher)
  27326.   return(1)
  27327. end
  27328.  
  27329. select @publication_type = publication_type from MSpublications
  27330.   where publisher_id = @srvid and
  27331.   publisher_db = @publisher_db and
  27332.   publication = @publication
  27333.  
  27334. if @publication_type is NULL
  27335. begin
  27336.   RAISERROR(21332, 16, -1, @publication)
  27337.   return(1)
  27338. end
  27339.  
  27340. create table #T_VERIFICATION_RESULTS (
  27341.   subscriber sysname NOT NULL, subscriber_db sysname NOT NULL, type int NOT NULL,
  27342.   job_id binary(16) NULL, results varchar(300) NULL
  27343. )
  27344.  
  27345. -- Parameter Check: @publication_type
  27346. -- Make sure that the publication type is one of the following:
  27347. -- 0  transactional
  27348. -- 1  snapshot
  27349. -- 2  merge
  27350. if( @publication_type = 0 or @publication_type = 1 )
  27351.   begin
  27352.     select @agent_type = 'distribution'
  27353.  
  27354.     create table #T_SUBSCRIPTIONS (subscriber sysname NOT NULL,  status int NOT NULL, 
  27355.     subscriber_db sysname NOT NULL,
  27356.     type tinyint NOT NULL, distribution_agent nvarchar(100) NOT NULL, last_action nvarchar(255) NULL, 
  27357.     action_time nvarchar(24) NULL, start_time nvarchar(24) NULL, duration int NULL, 
  27358.     delivery_rate float NULL,
  27359.     delivery_latency int NULL, delivered_transactions int NULL, 
  27360.     delivered_commands int NULL,
  27361.     delivery_time int NULL, average_commands int NULL, 
  27362.     error_id int NULL, 
  27363.     job_id binary(16) NULL, local_job bit NULL, profile_id int NOT NULL,
  27364.     agent_id int NOT NULL, last_timestamp binary(8) NOT NULL, offload_enabled bit NOT NULL, 
  27365.     offload_server sysname NULL, subscriber_type tinyint NULL)
  27366.  
  27367.     insert #T_SUBSCRIPTIONS
  27368.       exec sp_MSenum_subscriptions @publisher, @publisher_db, @publication
  27369.  
  27370.     insert into #T_VERIFICATION_RESULTS (subscriber, subscriber_db, type, job_id)
  27371.     (select subscriber, subscriber_db, type, job_id from #T_SUBSCRIPTIONS)
  27372.  
  27373.     drop table #T_SUBSCRIPTIONS
  27374.   end
  27375. else if( @publication_type = 2 )
  27376.   begin
  27377.     select @agent_type = 'merge'
  27378.  
  27379.     create table #T_MERGE_SUBSCRIPTIONS (subscriber sysname NOT NULL,  status int NOT NULL, 
  27380.         subscriber_db sysname NOT NULL, type int NOT NULL, agent_name nvarchar(100) NOT NULL, last_action nvarchar(255) NULL, 
  27381.         action_time nvarchar(24) NULL, start_time nvarchar(24) NULL, duration int NULL, 
  27382.         delivery_rate float NULL,
  27383.         publisher_insertcount int NULL, publisher_updatecount int NULL, publisher_deletecount int NULL,
  27384.         publisher_conficts int NULL, 
  27385.         subscriber_insertcount int NULL, subscriber_updatecount int NULL, subscriber_deletecount int NULL,
  27386.         subscriber_conficts int NULL, error_id int NULL, job_id binary(16) NULL,
  27387.         local_job bit NULL, profile_id int NOT NULL, 
  27388.         agent_id int NOT NULL, last_timestamp binary(8) NOT NULL, offload_enabled bit NOT NULL, 
  27389.     offload_server sysname NULL, subscriber_type tinyint NULL)
  27390.  
  27391.     insert #T_MERGE_SUBSCRIPTIONS
  27392.       exec sp_MSenum_merge_subscriptions @publisher, @publisher_db, @publication
  27393.  
  27394.     insert into #T_VERIFICATION_RESULTS (subscriber, subscriber_db, type, job_id)
  27395.     (select subscriber, subscriber_db, type, job_id from #T_MERGE_SUBSCRIPTIONS)
  27396.  
  27397.     drop table #T_MERGE_SUBSCRIPTIONS
  27398.   end
  27399. else
  27400.   begin
  27401.     drop table #T_VERIFICATION_RESULTS
  27402.     RAISERROR(20033, 16, -1)
  27403.     return(1)
  27404.   end
  27405.  
  27406. if( not exists( select * from #T_VERIFICATION_RESULTS ) )
  27407. begin
  27408.   --
  27409.   --if #T_VERIFICATION_RESULTS is empty, then there's no subscriptions
  27410.   --
  27411.   RAISERROR(14135, 16, -1, @publisher, @publisher_db, @publication)
  27412.   drop table #T_VERIFICATION_RESULTS
  27413.   return(1)
  27414. end
  27415.  
  27416. declare subscribers_cursor cursor LOCAL FAST_FORWARD for
  27417. select subscriber, subscriber_db, type, job_id
  27418.   from #T_VERIFICATION_RESULTS
  27419.   order by subscriber, subscriber_db
  27420.  
  27421. open subscribers_cursor
  27422. fetch next from subscribers_cursor
  27423.   into @subscriber, @subscriber_db, @type, @job_id
  27424. while @@FETCH_STATUS = 0
  27425. begin
  27426.   if( @type = 0 )
  27427.   begin
  27428.     --
  27429.     --local push subscription
  27430.     --
  27431.     select @command = ''
  27432.     select @success = 'unknown'
  27433.     select @command = command from msdb.dbo.sysjobsteps
  27434.       where job_id = @job_id and
  27435.         subsystem = case @publication_type  -- 0 = Transactional 1 = Snapshot 2 = Merge
  27436.           when 0 then N'Distribution'
  27437.           when 1 then N'Distribution'
  27438.           when 2 then N'Merge'
  27439.         end
  27440.  
  27441.     exec master.dbo.xp_replproberemsrv 'local', @agent_type, @success OUTPUT, @command, 1 --(islocal)
  27442.     if( @@ERROR <> 0) return(1)
  27443.     if UPPER(@success) = 'FALSE'
  27444.       select 'subscriber' = @subscriber, 'subscriber database' = @subscriber_db,
  27445.          'subscription type' = case @type
  27446.             when 0 then 'push'
  27447.             when 1 then 'pull'
  27448.             when 2 then 'anonymous'
  27449.             else 'unknown'
  27450.           end
  27451.          , 'results' = 'connection failed'
  27452.     else if( ( CHARINDEX('TRUE', UPPER(@success)) = 1 ) and (LEN(@success) = 4) )
  27453.       select @success = 'connection succeeded'
  27454.   end
  27455.   else
  27456.   begin
  27457.     --
  27458.     --non-push subscription, not supported
  27459.     --
  27460.     select @success = 'only push subscriptions can be verified with this stored procedure'
  27461.   end
  27462.  
  27463.   update #T_VERIFICATION_RESULTS set results = @success where
  27464.     subscriber = @subscriber and
  27465.     subscriber_db = @subscriber_db and
  27466.     type = @type and
  27467.     job_id = @job_id
  27468.   --
  27469.   --get next subscription
  27470.   --
  27471.   fetch next from subscribers_cursor
  27472.     into @subscriber, @subscriber_db, @type, @job_id
  27473. end
  27474. close subscribers_cursor
  27475. deallocate subscribers_cursor
  27476.  
  27477. select subscriber, subscriber_db as 'subscriber database', 'subscription type' =
  27478.   case type
  27479.     when 0 then 'push'
  27480.     when 1 then 'pull'
  27481.     when 2 then 'anonymous'
  27482.     else 'unknown'
  27483.   end
  27484. , results from #T_VERIFICATION_RESULTS where UPPER(results) != 'FALSE'
  27485.  
  27486. drop table #T_VERIFICATION_RESULTS
  27487. END
  27488. go
  27489. EXEC dbo.sp_MS_marksystemobject sp_verify_publication
  27490.  
  27491. ---------------------------------------------------------------------------
  27492. ---------------------------------------------------------------------------
  27493.  
  27494. grant execute on dbo.sp_enumfullsubscribers to public
  27495. grant execute on dbo.sp_addpublication to public
  27496. grant execute on dbo.sp_changepublication to public
  27497. grant execute on dbo.sp_changesubscription to public
  27498. grant execute on dbo.sp_articlecolumn to public
  27499. grant execute on dbo.sp_helparticle to public
  27500. grant execute on dbo.sp_helparticlecolumns to public
  27501. grant execute on dbo.sp_helppublication to public
  27502. grant execute on dbo.sp_publication_validation to public
  27503. grant execute on dbo.sp_marksubscriptionvalidation to public
  27504. grant execute on dbo.sp_article_validation to public
  27505. grant execute on dbo.sp_helpsubscription to public
  27506. grant execute on dbo.sp_MSscript_article_view to public
  27507. grant execute on dbo.sp_articlefilter to public
  27508. grant execute on dbo.sp_articleview to public
  27509. grant execute on dbo.sp_addarticle to public
  27510. grant execute on dbo.sp_MSgettranconflictname to public
  27511. grant execute on dbo.sp_MSmaketrancftproc to public
  27512. grant execute on dbo.sp_MSmakeconflicttable to public
  27513. grant execute on dbo.sp_scriptsubconflicttable to public
  27514. grant execute on dbo.sp_changesubstatus to public
  27515. grant execute on dbo.sp_addsubscription to public
  27516. grant execute on dbo.sp_changearticle to public
  27517. grant execute on dbo.sp_droparticle to public
  27518. grant execute on dbo.sp_droppublication to public
  27519. grant execute on dbo.sp_dropsubscription to public
  27520. grant execute on dbo.sp_subscribe to public
  27521. grant execute on dbo.sp_unsubscribe to public
  27522. grant execute on dbo.sp_refreshsubscriptions to public
  27523. grant execute on dbo.sp_reinitsubscription to public
  27524. grant exec on dbo.sp_articlesynctranprocs to public
  27525. go
  27526.  
  27527. grant exec on dbo.sp_gettypestring to public
  27528. grant exec on dbo.sp_scriptpkwhereclause to public
  27529. grant exec on dbo.sp_scriptupdateparams to public
  27530. grant exec on dbo.sp_scriptreconwhereclause to public
  27531. grant exec on dbo.sp_script_reconciliation_insproc to public
  27532. grant exec on dbo.sp_script_reconciliation_delproc to public
  27533. grant exec on dbo.sp_script_reconciliation_xdelproc to public
  27534. grant exec on dbo.sp_scriptinsproc to public
  27535. grant exec on dbo.sp_scriptdelproc to public
  27536. grant exec on dbo.sp_scriptxdelproc to public
  27537. grant exec on dbo.sp_scriptupdproc to public
  27538. grant exec on dbo.sp_scriptmappedupdproc to public
  27539. grant exec on dbo.sp_scriptxupdproc to public
  27540. grant exec on dbo.sp_MSscriptmvastablenci to public
  27541. grant exec on dbo.sp_MSscriptmvastablepkc to public
  27542. grant exec on dbo.sp_MSscriptmvastableidx to public
  27543. grant exec on dbo.sp_MSscriptmvastable to public
  27544. grant exec on dbo.sp_script_synctran_commands to public
  27545. grant exec on dbo.sp_MSget_synctran_commands to public
  27546. grant exec on dbo.sp_MSactivate_auto_sub to public
  27547. grant exec on dbo.sp_dropanonymousagent to public
  27548. go
  27549.  
  27550. grant execute on dbo.sp_MSscript_compensating_send to public
  27551. grant execute on dbo.sp_MSscript_insert_statement to public
  27552. grant execute on dbo.sp_MSscript_insert_subwins to public
  27553. grant execute on dbo.sp_MSscript_insert_pubwins to public
  27554. grant execute on dbo.sp_MSscript_update_statement to public
  27555. grant execute on dbo.sp_MSscript_update_subwins to public
  27556. grant execute on dbo.sp_MSscript_update_pubwins to public
  27557. grant execute on dbo.sp_MSscript_delete_statement to public
  27558. grant execute on dbo.sp_MSscript_delete_subwins to public
  27559. grant execute on dbo.sp_MSscript_compensating_insert to public
  27560. grant execute on dbo.sp_MSscript_delete_pubwins to public
  27561. grant execute on dbo.sp_MSscript_beginproc  to public
  27562. grant execute on dbo.sp_MSscript_security  to public
  27563. grant execute on dbo.sp_MSscript_endproc  to public
  27564. grant execute on dbo.sp_MSscript_sync_ins_proc  to public
  27565. grant execute on dbo.sp_MSscript_sync_upd_proc  to public
  27566. grant execute on dbo.sp_MSscript_sync_del_proc  to public
  27567. grant execute on dbo.sp_MSscript_ExecutionMode_stmt to public
  27568. grant execute on dbo.sp_MSscript_pub_upd_trig  to public
  27569. grant execute on dbo.sp_MSmark_proc_norepl to public
  27570. grant execute on dbo.sp_MSpub_adjust_identity to public
  27571. grant execute on dbo.sp_helparticledts to public
  27572. grant execute on dbo.sp_changesubscriptiondtsinfo to public
  27573. grant execute on dbo.sp_MSvalidate_subscription to public
  27574. grant exec on dbo.sp_MScomputearticlescreationorder to public
  27575. grant exec on dbo.sp_MScomputeunresolvedrefs to public
  27576. go
  27577.  
  27578. grant execute on dbo.sp_MShelptranconflictpublications to public
  27579. grant execute on dbo.sp_MShelptranconflictcounts to public
  27580. grant execute on dbo.sp_MSgettranconflictrow to public
  27581. grant execute on dbo.sp_MSgettrancftsrcrow to public
  27582. grant execute on dbo.sp_MSdeletetranconflictrow to public
  27583. grant execute on dbo.sp_MSgetarticlereinitvalue to public
  27584. grant execute on dbo.sp_MSispkupdateinconflict to public
  27585. grant execute on dbo.sp_ivindexhasnullcols to public
  27586. grant execute on dbo.fn_sqlvarbasetostr to public
  27587. grant execute on dbo.sp_replrestart to public
  27588. grant execute on dbo.sp_replsqlqgetrows to public
  27589. grant execute on dbo.sp_MSrepl_schema to public
  27590. grant execute on dbo.sp_MSpost_auto_proc to public
  27591. grant execute on dbo.sp_MSreplupdateschema to public
  27592. grant execute on dbo.sp_MSdefer_check to public
  27593. grant execute on dbo.sp_MSreenable_check to public
  27594. grant execute on dbo.sp_getqueuedrows to public
  27595. grant execute on dbo.sp_MSprep_exclusive to public
  27596. grant execute on dbo.sp_verify_publication to public
  27597. grant execute on dbo.sp_MSexternalfkreferences to public
  27598. go 
  27599.  
  27600. dump tran master with no_log
  27601. go
  27602. sp_configure 'allow updates',0
  27603. go
  27604. reconfigure with override
  27605. go
  27606.  
  27607. print ''
  27608. print 'Checking objects created by repltran.sql.'
  27609. go
  27610.  
  27611. --obsolete   exec dbo.sp_check_objects 'repl'
  27612. -- exec dbo.sp_MS_upd_sysobj_category 2  --set sysobjects.category | 2 based on crdate.
  27613. go
  27614.  
  27615.  
  27616. print ''
  27617. print 'repltran.sql completed successfully.'
  27618. go
  27619.  
  27620. dump tran master with no_log
  27621. go
  27622. checkpoint
  27623. go
  27624.