home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Internet Business Development Kit / PRODUCT_CD.iso / sqlsvr / ppc / sqlole60.sql < prev    next >
Encoding:
Text File  |  1995-12-13  |  100.8 KB  |  2,864 lines

  1.  
  2.  
  3.  
  4.  
  5.  
  6.  
  7.  
  8.  
  9.  
  10.  
  11.  
  12. /* Preprocessor directives, will be blank space in output .sql file. */
  13.  
  14.  
  15.  
  16.  
  17.  
  18.  
  19.  
  20.  
  21.  
  22. /* For fetching from cursor */
  23.  
  24.  
  25.  
  26.  
  27.  
  28.  
  29.  
  30.  
  31.  
  32.  
  33.  
  34.  
  35.  
  36.  
  37.  
  38.  
  39.  
  40.  
  41.  
  42.  
  43.  
  44.  
  45.  
  46.  
  47.  
  48.  
  49.  
  50.  
  51.  
  52.  
  53.  
  54.  
  55.  
  56.  
  57.  
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72.  
  73.  
  74.  
  75.  
  76.  
  77.  
  78. /* status values for these. */
  79.  
  80.  
  81.  
  82.  
  83.  
  84.  
  85.  
  86. /* bitmask values for same; power(2, DRI_*). */
  87.  
  88.  
  89.  
  90.  
  91.  
  92.  
  93.  
  94.  
  95.  
  96.  
  97.  
  98.  
  99.  
  100.  
  101.  
  102.  
  103.  
  104.  
  105. /* DRI-generated index masks, to apply to sysindexes.status */
  106.  
  107.  
  108.  
  109.  
  110.  
  111.  
  112. /* sysobjects.category bit that indicates this is an MS-internal object. */
  113.  
  114.  
  115. /* sysobjects.category bit for an sp_ that indicates it's a startup proc, or an xp that should ImpersonateClient. */
  116.  
  117.  
  118.  
  119. /* BIT_CLUSTERED indicates the key is clustered. */
  120. /* EXCLUDE REPLICATION value in sysconstraints.status, and system-generated name. */
  121.  
  122.  
  123.  
  124.  
  125. /* sysobjects.sysstat bits (lower 4) that mask off the object type. */
  126.  
  127.  
  128. /* bit for DEFAULTS which are really DRI-created. */
  129.  
  130.  
  131. /* bits for columns - don't conflict with bit_sysgenname for DRIDefaults. */
  132.  
  133.  
  134.  
  135.  
  136.  
  137.  
  138. /* sysdatabases.category bits */
  139.  
  140.  
  141.  
  142.  
  143.  
  144.  
  145. /* From SQLOLE.H, MUST BE SYNC'd!!! */
  146.  
  147.  
  148.  
  149.  
  150.  
  151.  
  152.  
  153.  
  154.  
  155.  
  156.  
  157.  
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172.  
  173.  
  174.  
  175.  
  176.  
  177.  
  178.  
  179.  
  180.  
  181.  
  182.  
  183.  
  184. /* From perm.h */
  185.  
  186.  
  187.  
  188.  
  189.  
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.  
  200. /* Localized error-string files (PRE95_ERRMSG_*) for PRE95 servers. */
  201. /* Set the include path to determine which lang-specific version is picked up. */
  202.  
  203. /* USA-localized strings for 4.21 localization of sqlole.cxx */
  204. /* Should match the localized string in sysmessages (see sqlole.cxx for message number). */
  205.  
  206.  
  207.  
  208.  
  209.  
  210.  
  211.  
  212.  
  213.  
  214.  
  215.  
  216.  
  217. use master
  218. go
  219.  
  220. /************* DUMP THE TRANSACTION LOG **************************************/
  221. /* Comment this out if you don't want your log dumped.  If you rerun this    */
  222. /* script periodically, you will run out of transaction log space.           */
  223. print ''
  224. print 'Dumping transaction log...'
  225. print ''
  226. go
  227. dump tran master with no_log
  228. go
  229. /************* END DUMP THE TRANSACTION LOG **********************************/
  230.  
  231. /********************* Delete existing objects *********************************/
  232. print ''
  233. print 'Deleting existing objects...'
  234. print ''
  235. go
  236.  
  237.  
  238.  
  239.  
  240.  
  241. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MShelpcolumns')
  242.     drop procedure sp_MShelpcolumns
  243. go
  244. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MShelpindex')
  245.     drop procedure sp_MShelpindex
  246. go
  247. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MShelptype')
  248.     drop procedure sp_MShelptype
  249. go
  250. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSdependencies')
  251.     drop procedure sp_MSdependencies
  252. go
  253. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MStablespace')
  254.     drop procedure sp_MStablespace
  255. go
  256. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSindexspace')
  257.     drop procedure sp_MSindexspace
  258. go
  259. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSuniquename')
  260.     drop procedure sp_MSuniquename
  261. go
  262. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSkilldb')
  263.     drop procedure sp_MSkilldb
  264. go
  265. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSdbuserprofile')
  266.     drop procedure sp_MSdbuserprofile
  267. go
  268. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSobjectprivs')
  269.     drop procedure sp_MSobjectprivs
  270. go
  271.  
  272.  
  273. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSgetalertinfo')
  274.     drop procedure sp_MSgetalertinfo
  275. go
  276. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSsetalertinfo')
  277.     drop procedure sp_MSsetalertinfo
  278. go
  279. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSgetexecinfo')
  280.     drop procedure sp_MSgetexecinfo
  281. go
  282. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSsetexecinfo')
  283.     drop procedure sp_MSsetexecinfo
  284. go
  285. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MStablekeys')
  286.     drop procedure sp_MStablekeys
  287. go
  288. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MStablechecks')
  289.     drop procedure sp_MStablechecks
  290. go
  291. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MStablerefs')
  292.     drop procedure sp_MStablerefs
  293. go
  294. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSsettopology')
  295.     drop procedure sp_MSsettopology
  296. go
  297. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSfilterclause')
  298.     drop procedure sp_MSfilterclause
  299. go
  300. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSmatchkey')
  301.     drop procedure sp_MSmatchkey
  302. go
  303. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSsubscriptions')
  304.     drop procedure sp_MSsubscriptions
  305. go
  306. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSforeachdb')
  307.     drop procedure sp_MSforeachdb
  308. go
  309. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSforeachtable')
  310.     drop procedure sp_MSforeachtable
  311. go
  312. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSloginmappings')
  313.     drop procedure sp_MSloginmappings
  314. go
  315. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSforeach_worker')
  316.     drop procedure sp_MSforeach_worker
  317. go
  318.  
  319. if exists (select * from master..sysobjects where sysstat & 0x0f = 4 and name = 'sp_MSSQLOLE_version')
  320.     drop procedure sp_MSSQLOLE_version
  321. go
  322.  
  323. /********************* Create new objects *********************************/
  324.  
  325. /*******************************************************************************/
  326. print ''
  327. print 'Creating sp_MShelpcolumns'
  328. print ''
  329. go
  330. create procedure sp_MShelpcolumns
  331. @tablename varchar(92), @flags int = 0, @orderby varchar(10) = null
  332. as
  333.     if (@tablename = '?')
  334.     begin
  335.         print ''
  336.         print 'Usage:  sp_MShelpcolumns @tablename, @flags int = 0'
  337.         print ' where @flags is a bitmask of:'
  338.         print ' 0x0200        = No DRI (ignore Checks, Primary/Foreign/Unique Keys, etc.)'
  339.         print ' 0x0400        = UDDTs --> Base type'
  340.         print ' 0x0800        = 42Syntax (convert numeric/decimal, no identity)'
  341.         print ' 0x80000        = TimestampToBinary (convert timestamp cols to binary(8))'
  342.         print ' 0x40000000    = No Identity attribute'
  343.         return 0
  344.     end
  345.  
  346.     
  347.     if (object_id(@tablename) is null)
  348.     begin
  349.         
  350.         RAISERROR (15001, -1, -1, @tablename)
  351.         return 1
  352.     end
  353.  
  354.     set nocount on
  355.  
  356.     create table #sphelpcols
  357.     (
  358.         col_name        varchar (30),
  359.         col_id            tinyint,
  360.         col_type        smallint,
  361.         col_len            tinyint,
  362.         col_prec        tinyint    null,
  363.         col_scale        tinyint    null,
  364.         col_def            int        null,
  365.         col_rul            int        null,
  366.         col_null        bit,                /* status & 8 */
  367.         col_identity    bit,                /* status & 128 */
  368.         col_defname        varchar(61) null,    /* fully-qual'd default name, or NULL */
  369.         col_rulname        varchar(61) null,    /* fully-qual'd rule name, or NULL */
  370.         col_basetype    int        null,
  371.         col_flags        int        null,
  372.         col_seed        int        null,
  373.         col_increment    int     null,
  374.         col_dridefname    varchar(30) null,    /* DRI DEFAULT name */
  375.         col_drideftext    varchar(255) null    /* DRI DEFAULT text */
  376.     )
  377.  
  378.     /* First load stuff so we can blot off inappropriate info and massage as per @flags */
  379.     insert #sphelpcols
  380.     select name, colid, usertype, length, prec, scale, cdefault, domain,
  381.             convert(bit, status & 0x0008), convert(bit, status & 0x0080), NULL, NULL, type, 0, null, null, null, null
  382.     from syscolumns
  383.     where id = object_id(@tablename)
  384.  
  385.     /* Convert any timestamp column to binary(8) if they asked. */
  386.     if (@flags is not null and @flags & 0x80000 != 0)
  387.         update #sphelpcols set col_type = 3, col_len = 8 where col_type = 80
  388.  
  389.  
  390.     /* If they have a column dridefault, then this will show up in syscolumns.cdefault.  Filter that; */
  391.     /* we'll put in the real dridefault below if they don't have NoDRI set. */
  392.     update #sphelpcols set col_def = null where exists (select * from sysconstraints s, #sphelpcols c
  393.         where s.colid = c.col_id and s.id = object_id(@tablename) and s.status & 0x0f = 5)
  394.  
  395.     /* Clear out identity if so requested.*/
  396.     if (@flags is not null and @flags & 0x40000000 != 0)
  397.         update #sphelpcols set col_identity = 0
  398.  
  399.  
  400.     /* Convert from the dblib-specific 'nullable' type to something people and the server recognize. */
  401.     /* datetime --> datetimn */
  402.     update #sphelpcols set col_type = 12 where col_type = 15
  403.     /* decimal --> decimaln */
  404.     update #sphelpcols set col_type = 24 where col_type = 26
  405.     /* float --> floatn */
  406.     update #sphelpcols set col_type = 8 where col_type = 14
  407.     /* int --> intn*/
  408.     update #sphelpcols set col_type = 7 where col_type = 13
  409.     /* money --> moneyn*/
  410.     update #sphelpcols set col_type = 11 where col_type = 17
  411.     /* numeric --> numericn */
  412.     update #sphelpcols set col_type = 10 where col_type = 25
  413.  
  414.     /* Set the physical base datatype to col_type if it's not a usertype, else to the actual physical basetype. */
  415.     update #sphelpcols set col_basetype = col_type where col_type < 100
  416.     update #sphelpcols set col_basetype = bt.usertype
  417.         from systypes bt
  418.         where col_type > 100 and bt.type = col_basetype and bt.usertype < 99 and bt.usertype not in (18, 80)
  419.  
  420.     /* Now do the same conversion for the physical base datatype. */
  421.     /* datetime --> datetimn */
  422.     update #sphelpcols set col_basetype = 12 where col_basetype = 15
  423.     /* decimal --> decimaln */
  424.     update #sphelpcols set col_basetype = 24 where col_basetype = 26
  425.     /* float --> floatn */
  426.     update #sphelpcols set col_basetype = 8 where col_basetype = 14
  427.     /* int --> intn*/
  428.     update #sphelpcols set col_basetype = 7 where col_basetype = 13
  429.     /* money --> moneyn*/
  430.     update #sphelpcols set col_basetype = 11 where col_basetype = 17
  431.     /* numeric --> numericn */
  432.     update #sphelpcols set col_basetype = 10 where col_basetype = 25
  433.  
  434.     /* Make a nice, presentable qualified rule/default name for those which are non-null */
  435.     update #sphelpcols set col_defname = user_name(d.uid) + '.' + d.name
  436.             from #sphelpcols c, sysobjects d where c.col_def is not null and d.id = c.col_def
  437.     update #sphelpcols set col_rulname = user_name(r.uid) + '.' + r.name
  438.             from #sphelpcols c, sysobjects r where c.col_rul is not null and r.id = c.col_rul
  439.  
  440.     /* Now see what our flags are, if anything.  Ignore the physical base type here -- these */
  441.     /* flags are just for scripting, which doesn't use that. */
  442.     if (@flags is not null and @flags != 0)
  443.     begin
  444.         if (@flags & 0x0400 != 0)
  445.         begin
  446.             /* Track from usertype --> b.<base>type --> u.usertype in systypes */
  447.             update #sphelpcols set col_type = u.usertype from #sphelpcols c, systypes b, systypes u
  448.             where c.col_type > 100 and b.usertype = c.col_type and b.type = u.type and u.usertype < 100 and u.usertype not in (18, 80)
  449.         end
  450.  
  451.         /* Modifided to allow Identity if NoDRI.  This is like a new datatype; OK unless 42Syntax is specified. */
  452.         if (@flags & 0x0800 != 0)
  453.         begin
  454.             update #sphelpcols                /* No IDENTITY */
  455.                 set col_identity = 0
  456.             update #sphelpcols                /* Convert numeric and decimal with prec < 8 to real */
  457.                 set col_type = 23 where col_type in (10, 24) and col_prec < 8
  458.             update #sphelpcols                /* Convert numeric and decimal with prec >= 8 to float */
  459.                 set col_type = 8 where col_type in (10, 24)    and col_prec >= 8
  460.         end
  461.  
  462.     end
  463.  
  464.  
  465.     /* Modifided to allow Identity if NoDRI.  This is like a new datatype; OK unless 42Syntax is specified. */
  466.     update #sphelpcols set col_seed = ident_seed(@tablename), col_increment = ident_incr(@tablename) where col_identity != 0
  467.  
  468.     /* Get seed and increment for the IDENTITY column, if any. */
  469.     if (@flags is null or @flags & 0x0200 = 0) begin
  470.         update #sphelpcols set col_dridefname = object_name(s.constid) from sysconstraints s, #sphelpcols c
  471.             where s.colid = c.col_id and s.id = object_id(@tablename) and s.status & 0x0f = 5
  472.  
  473.         /* Determine if the column is in the primary key */
  474.         declare @ii int, @indid int, @keycnt int
  475.         select @indid = indid, @keycnt = keycnt from sysindexes i where i.id = object_id(@tablename) and i.status & 0x0800 <> 0
  476.         if (@indid is not null) begin
  477.             if (@indid <> 1) select @keycnt = @keycnt - 1    /* keycnt includes RID if nc index */
  478.             select @ii = 1
  479.             while @ii <= @keycnt begin
  480.                 update #sphelpcols set col_flags = col_flags | 0x0004 where index_col(@tablename, @indid, @ii) = col_name
  481.                 select @ii = @ii + 1
  482.             end
  483.         end
  484.  
  485.         /* We'll put out the default text if it's all in one row (most likely); otherwise leave it */
  486.         /* blank for refetching in its entirety via sp_helptext. */
  487.         update #sphelpcols set col_drideftext = t.text from syscomments t, sysconstraints s, #sphelpcols c
  488.             where s.colid = c.col_id and s.id = object_id(@tablename) and s.status & 0x0f = 5
  489.                 and t.id = s.constid and 1 = (select count(*) from syscomments where id = s.constid)
  490.     end
  491.  
  492.     /* Clear out precision/scale for nonnumerics */
  493.     update #sphelpcols set col_prec = null, col_scale = null where col_basetype not in (10, 24)
  494.  
  495.  
  496.  
  497.     /* For scripting, set the col_flags */
  498.     update #sphelpcols set col_flags = col_flags | 0x0001 where col_type in (1,2,3,4)
  499.     update #sphelpcols set col_flags = col_flags | 0x0002 where col_type in (10, 24)
  500.  
  501.     /* OK, now put out the data */
  502.     set nocount off
  503.     if (@orderby is null or @orderby = 'id')
  504.     begin
  505.         select c.col_name, c.col_id, DataType = t.name, c.col_len, c.col_prec, c.col_scale,
  506.                 BaseType = b.name, c.col_defname, c.col_rulname, c.col_null, c.col_identity,
  507.                 c.col_flags, c.col_seed, c.col_increment, c.col_dridefname, c.col_drideftext
  508.         from #sphelpcols c, systypes t, systypes b
  509.         where t.usertype = c.col_type and b.usertype = c.col_basetype
  510.         order by c.col_id
  511.     end else begin
  512.         select c.col_name, c.col_id, DataType = t.name, c.col_len, c.col_prec, c.col_scale,
  513.                 BaseType = b.name, c.col_defname, c.col_rulname, c.col_null, c.col_identity,
  514.                 c.col_flags, c.col_seed, c.col_increment, c.col_dridefname, c.col_drideftext
  515.         from #sphelpcols c, systypes t, systypes b
  516.         where t.usertype = c.col_type and b.usertype = c.col_basetype
  517.         order by c.col_name
  518.     end
  519. go
  520. /* End sp_MShelpcolumns */
  521.  
  522. /*******************************************************************************/
  523. print ''
  524. print 'Creating sp_MShelpindex'
  525. print ''
  526. go
  527. create procedure sp_MShelpindex
  528. @tablename varchar(92), @indexname varchar(30) = null
  529. as
  530.  
  531.     select i.name, i.status, i.indid, i.OrigFillFactor,
  532.  
  533.  
  534.  
  535.         index_col(@tablename, i.indid, 1), index_col(@tablename, i.indid, 2),
  536.         index_col(@tablename, i.indid, 3), index_col(@tablename, i.indid, 4),
  537.         index_col(@tablename, i.indid, 5), index_col(@tablename, i.indid, 6),
  538.         index_col(@tablename, i.indid, 7), index_col(@tablename, i.indid, 8),
  539.         index_col(@tablename, i.indid, 9), index_col(@tablename, i.indid, 10),
  540.         index_col(@tablename, i.indid, 11), index_col(@tablename, i.indid, 12),
  541.         index_col(@tablename, i.indid, 13), index_col(@tablename, i.indid, 14),
  542.         index_col(@tablename, i.indid, 15), index_col(@tablename, i.indid, 16)
  543.     from sysindexes i where id = object_id(@tablename) and i.indid > 0 and i.indid < 255
  544.     and (@indexname is null or i.name = @indexname)
  545.     order by i.name
  546. go
  547. /* End sp_MShelpindex */
  548.  
  549. /*******************************************************************************/
  550. print ''
  551. print 'Creating sp_MShelptype'
  552. print ''
  553. go
  554. create procedure sp_MShelptype
  555. @typename varchar(92) = null, @flags varchar(10) = null
  556. as
  557.     if (@typename = '?')
  558.     begin
  559.         print ''
  560.         print 'Usage:  sp_MShelptype @typeename = null, @flags varchar(10) = null'
  561.         print ' where @flags is either:'
  562.         print ' sdt        = look in system datatypes'
  563.         print ' uddt      = look in user defined datatypes'
  564.         print ' null    = look wherever its found'
  565.         print ''
  566.         return 0
  567.     end
  568.  
  569.     /* Catch typos... */
  570.     if (@flags is not null and @flags not in ('sdt', 'uddt'))
  571.         select @flags = null
  572.  
  573.     
  574.  
  575.     /* Find out what type we're gonna be looking in, if they gave us a name. */
  576.     if (@typename is not null)
  577.     begin
  578.         declare @usertype int
  579.         select @usertype = usertype from systypes where name = @typename
  580.         if (@usertype is not null)
  581.         begin
  582.             if (@usertype < 100)
  583.             begin
  584.                 if (@flags is null)
  585.                     select @flags = 'sdt'
  586.                 if (@flags != 'sdt')
  587.                     select @usertype = null
  588.             end else begin
  589.                 if (@flags is null)
  590.                     select @flags = 'uddt'
  591.                 if (@flags != 'uddt')
  592.                     select @usertype = null
  593.             end
  594.         end
  595.         if (@usertype is null)
  596.         begin
  597.             
  598.             RAISERROR (15001, -1, -1, @typename)
  599.             return 1
  600.         end
  601.     end
  602.  
  603.     /* Now go get the info, depending on the type they gave us. */
  604.     if (@flags is null or @flags = 'sdt')
  605.     begin
  606.         /* Exclude the 'xxxxn' dblib-specific nullable types, and hardcode a check for variable length and numeric usertypes. */
  607.         select     SystemDatatypeName = t.name,
  608.                 ifvarlen_max = y.length,
  609.                 allownulls = t.allownulls,
  610.  
  611.                 isnumeric = (select count(*) from systypes y where y.usertype = t.usertype and y.usertype in (24,10)),
  612.                 allowidentity = case when t.usertype in (24,7,10,6,5) then 1 else 0 end
  613.  
  614.  
  615.  
  616.             from systypes t, systypes y
  617.             where t.usertype < 100 and t.usertype not in (15,26,14,13,17,25) and (@typename is null or t.name like @typename)
  618.             and y.usertype =* t.usertype and y.usertype in (1,2,3,4)
  619.             order by t.name
  620.     end
  621.  
  622.     /* Need a temp table so we can ownerqualify nonNULL rules/defaults. */
  623.     create table #sphelptype (
  624.         dt_usertype    int        null,
  625.         dt_basetype int        null,
  626.         dt_rul         int        null,
  627.         dt_def         int        null,
  628.         dt_rulname     varchar(61) null,
  629.         dt_defname    varchar(61) null,
  630.         dt_flags    int        null
  631.     )
  632.  
  633.     if (@flags is null or @flags = 'uddt')
  634.     begin
  635.         set nocount on
  636.         insert #sphelptype (dt_usertype, dt_basetype, dt_rul, dt_def, dt_flags)
  637.             select t.usertype,
  638.             (select distinct b.usertype from systypes b where b.type = t.type and b.usertype < 100 and b.usertype not in (18, 80)),
  639.             t.domain, t.tdefault, 0
  640.             from systypes t
  641.             where t.usertype > 99 and (@typename is null or t.name like @typename)
  642.  
  643.         /* Make a nice, presentable qualified rule/default name for those which are non-null */
  644.         update #sphelptype set dt_defname = user_name(d.uid) + '.' + d.name
  645.                 from #sphelptype c, sysobjects d where c.dt_def is not null and d.id = c.dt_def
  646.         update #sphelptype set dt_rulname = user_name(r.uid) + '.' + r.name
  647.                 from #sphelptype c, sysobjects r where c.dt_rul is not null and r.id = c.dt_rul
  648.  
  649.         /* For scripting, set the dt_flags -- these apply to the BASE datatype. */
  650.         update #sphelptype set dt_flags = dt_flags | 0x0001 where dt_basetype in (1,2,3,4)
  651.         update #sphelptype set dt_flags = dt_flags | 0x0002 where dt_basetype in (10, 24)
  652.  
  653.         set nocount off
  654.         select distinct UserDatatypeName = t.name,
  655.                 owner = user_name(t.uid),
  656.                 basetypename = (select distinct b.name from systypes b where b.usertype = s.dt_basetype),
  657.                 defaultname = dt_defname,
  658.                 rulename = dt_rulname,
  659.                 tid = t.usertype,
  660.  
  661.                 length = case when s.dt_basetype in (1,2,3,4) then t.length else 0 end,
  662.                 nullable = t.allownulls,
  663.                 dt_prec = case when s.dt_basetype in (10, 24) then t.prec else null end,
  664.                 dt_scale = case when s.dt_basetype in (10, 24) then t.scale else null end,
  665.                 dt_flags,
  666.                 allowidentity = case when (s.dt_basetype in (24,7,10,6,5) and scale = 0) then 1 else 0 end
  667.  
  668.  
  669.  
  670.             from systypes t, #sphelptype s
  671.             where t.usertype > 99 and (@typename is null or t.name like @typename)
  672.                 and dt_usertype = t.usertype
  673.             order by t.name
  674.     end
  675. go
  676. /* End sp_MShelptype */
  677.  
  678. /*******************************************************************************/
  679. print ''
  680. print 'Creating sp_MSdependencies'
  681. print ''
  682. go
  683.  
  684. create procedure sp_MSdependencies
  685. @objname varchar(92) = null, @objtype int = null, @flags int = 0x01fd
  686. as
  687.     if (@objname = '?')
  688.     begin
  689.         print 'sp_MSobject_dependencies name = NULL, type = NULL, flags = 0x01fd'
  690.         print '  name:  name or null (all objects of type)'
  691.         print '  type:  type number (see below) or null'
  692.         print '      if both null, get all objects in database'
  693.         print '  flags is a bitmask of the following values:'
  694.         print '      0x10000  = return multiple parent/child rows per object'
  695.         print '      0x20000  = descending return order'
  696.         print '      0x40000  = return children instead of parents'
  697.         print '      0x80000  = Include input object in output result set'
  698.         print '      0x100000 = return only firstlevel (immediate) parents/children'
  699.         print '      0x200000 = return only DRI dependencies'
  700.         print '      power(2, object type number(s))  to return in results set:'
  701.         print '          0 (1      - 0x0001)     - datatype'
  702.         print '          1 (2      - 0x0002)     - system tables or MS-internal objects'
  703.         print '          2 (4      - 0x0004)     - view'
  704.         print '          3 (8      - 0x0008)     - user table'
  705.         print '          4 (16        - 0x0010)     - procedure'
  706.         print '          5 (32        - 0x0020)     - log'
  707.         print '          6 (64     - 0x0040)     - default'
  708.         print '          7 (128    - 0x0080)     - rule'
  709.         print '          8 (256    - 0x0100)     - trigger'
  710.         print '      shortcuts:'
  711.         print '          29     (0x011c) - trig, view, user table, procedure'
  712.         print '          448    (0x00c1) - rule, default, datatype'
  713.         print '          509    (0x01fd) - all but systables/objects'
  714.         print '          511    (0x01ff) - all'
  715.         return 0
  716.     end
  717.  
  718.     /* If they want SQLOLEDep_DRIOnly, remove all but usertable objects from @flags */
  719.  
  720.     if (@flags & 0x200000 <> 0)
  721.         select @flags = (@flags & ~convert(int, 0x01ff)) | power(2, 3)
  722.  
  723.  
  724.     if (@objtype in (0, 5, 6, 7))
  725.     begin
  726.         /* Print only, do not raiserror as we may be calling this blindly and this is not a real error. */
  727.         print 'Rules, defaults, and datatypes do not have dependencies.'
  728.         return (0)
  729.     end
  730.  
  731.     /*
  732.      * Create #t1 and #t2 as temp object holding areas.  Columns are:
  733.      *     tid        - temp object id
  734.      *     ttype     - temp object type
  735.      *     pid        - parent or child object id
  736.      *     ptype     - parent or child object type
  737.      *     bDone     - NULL means dependencies not yet evaluated, else nonNULL.
  738.      */
  739.     declare @curid int, @curcat int, @rowsaffected int
  740.     declare @allobjs int
  741.     declare @delinputobj int
  742.     select @allobjs = 0, @delinputobj = 0, @curid = NULL, @curcat = NULL
  743.     create table #t1 (tid int NULL, ttype smallint NULL, tcat smallint NULL, pid int NULL, ptype smallint NULL, pcat smallint NULL, bDone smallint NULL)
  744.     create table #t2 (tid int NULL, ttype smallint NULL, tcat smallint NULL, pid int NULL, ptype smallint NULL, pcat smallint NULL, bDone smallint NULL)
  745.     create table #tempudt (dtype int)
  746.  
  747.     /* Worktables we'll use for optimization.  #t3 and #t4 push us over the 64 2K page limit in 4.21, */
  748.     /* but the real gain is from #temptrig anyway. */
  749.  
  750.     create table #t3 (tid int)
  751.     create clustered index #ci_t3 on #t3(tid) with allow_dup_row
  752.     create table #t4 (tid int)
  753.     create clustered index #ci_t4 on #t4(tid) with allow_dup_row
  754.  
  755.     create table #temptrig(id int, deltrig int, sysstat smallint, category int)
  756.     create clustered index #ci_temptrig on #temptrig (deltrig) with allow_dup_row
  757.  
  758.     
  759.  
  760.     /*
  761.      * If both name and type are null, this means get every object in the
  762.      * database matching the specification they passed in.  Otherwise,
  763.      * find the passed object or all objects of the passed type.  Start off
  764.      * loading parent info (pid, tid); these will be put into child as needed.
  765.      */
  766.     if (@objname is null and @objtype is null)
  767.     begin
  768.         set nocount on
  769.         select @allobjs = 1
  770.         insert #t1 (pid, ptype, pcat) select o.id, o.sysstat & 0x0f, o.category & 0x0002 from sysobjects o
  771.             where ((power(2, o.sysstat & 0x0f) & 0x01ff) <> 0) and (o.sysstat & 0x0f not in (6, 7))
  772.     end else begin
  773.         if (@objname is not null)
  774.         begin
  775.             select @curid = id, @objtype = o.sysstat & 0x0f, @curcat = o.category & 0x0002 from sysobjects o where id = object_id(@objname)
  776.             if (@curid is null)
  777.             begin
  778.                 
  779.                 RAISERROR (15001, -1, -1, @objname)
  780.                 return 1
  781.             end
  782.             if (@flags & 0x80000 = 0)
  783.                 select @delinputobj = @curid
  784.         end
  785.  
  786.         set nocount on
  787.         if (@curid is null)
  788.             insert #t1 (pid, ptype, pcat) select o.id, o.sysstat & 0x0f, o.category & 0x0002 from sysobjects o
  789.                 where o.sysstat & 0x0f = @objtype
  790.         else
  791.             insert #t1 (pid, ptype, pcat) values (@curid, @objtype, @curcat)
  792.     end
  793.  
  794.     /*
  795.      * All initial objects are loaded as parents/children.  Now we loop, creating
  796.      * rows of child/parent relationships.  Use #t2 as a temp area for the selects
  797.      * to simulate recursion; when they find no rows, we're done with this step.
  798.      *
  799.      * Note that triggers are weird; they're part of a table definition but can
  800.      * also reference other tables, so we need to evaluate them both ways.  SQL
  801.      * Server stores the table for a trigger object as its deltrig; if a trigger
  802.      * references another table, that relationship is stored in sysdepends.
  803.      * This peculiarity of triggers requires separating the object-retrieval pass
  804.      * from the creation-sequence pass (below).  Also, the fact that trigger tables
  805.      * are stored in a non-indexed column (deltrig) requires us to use a worktable
  806.      * if we're returning triggers, so we don't continually tablescan sysobjects.
  807.      */
  808.  
  809.     if (@flags & power(2, 8) != 0)
  810.         insert #temptrig select d.id, d.deltrig, d.sysstat, d.category from sysobjects d where d.sysstat & 0x0f = 8
  811.  
  812.     while (select count(*) from #t1 where bDone is null) > 0
  813.     begin
  814.         /*
  815.          * Remove Microsoft-internal or other system objects from #t1, unless
  816.          * @flags specified including system tables.  We do this here so that
  817.          * cascaded system dependencies are not included unless specifically
  818.          * requested.  For other restrictions, we wait until below so that all
  819.          * cascaded object types are fully evaluated.
  820.          */
  821.         if (@flags & power(2, 1) = 0)
  822.             delete #t1 where ttype = 1 or tcat = 0x0002 or pcat = 0x0002
  823.  
  824.         if (@flags & 0x40000 != 0)
  825.         begin
  826.             if (@flags & 0x200000 = 0) begin
  827.                 /* Table --> Triggers */
  828.                 if (@flags & power(2, 8) != 0)
  829.                     insert #t2 (tid, ttype, tcat, pid, ptype, pcat)
  830.                         select distinct t.pid, t.ptype, t.pcat, o.id, o.sysstat & 0x0f, o.category & 0x0002 from #t1 t, #temptrig o
  831.                             where t.bDone is null and t.ptype = 3 and o.deltrig = t.pid
  832.  
  833.                 /* Object --> sysdepends children */
  834.                 insert #t2 (tid, ttype, tcat, pid, ptype, pcat)
  835.                     select distinct t.pid, t.ptype, t.pcat, d.id, o.sysstat & 0x0f, o.category & 0x0002
  836.                     from #t1 t, sysdepends d, sysobjects o
  837.                     where t.bDone is null and d.depid = t.pid and d.id = o.id
  838.             end
  839.  
  840.             /* Object --> sysreferences children (FK tables referencing this one) */
  841.             insert #t2 (tid, ttype, tcat, pid, ptype, pcat)
  842.                 select distinct t.pid, t.ptype, t.pcat, r.fkeyid, o.sysstat & 0x0f, o.category & 0x0002
  843.                 from #t1 t, sysreferences r, sysobjects o
  844.                 where t.bDone is null and r.rkeyid = t.pid and r.fkeyid = o.id
  845.  
  846.         end else begin
  847.             if (@flags & 0x200000 = 0) begin
  848.                 /* Trigger --> Table */
  849.                 if (@flags & power(2, 3) != 0)
  850.                     insert #t2 (tid, ttype, tcat, pid, ptype, pcat)
  851.                         select distinct t.pid, t.ptype, t.pcat, o.deltrig, u.sysstat & 0x0f, u.category & 0x0002
  852.                               from #t1 t, sysobjects o, sysobjects u
  853.                             where t.bDone is null and t.ptype = 8 and o.id = t.pid and o.deltrig != 0 and u.id = o.deltrig
  854.  
  855.                 /* Object --> sysdepends parents */
  856.                 insert #t2 (tid, ttype, tcat, pid, ptype, pcat)
  857.                     select distinct t.pid, t.ptype, t.pcat, d.depid, o.sysstat & 0x0f, o.category & 0x0002
  858.                     from #t1 t, sysdepends d, sysobjects o
  859.                     where t.bDone is null and d.id = t.pid and d.depid = o.id
  860.             end
  861.  
  862.             /* Object --> sysreferences parents (PK/UQ tables referenced by one) */
  863.             insert #t2 (tid, ttype, tcat, pid, ptype, pcat)
  864.                 select distinct t.pid, t.ptype, t.pcat, r.rkeyid, o.sysstat & 0x0f, o.category & 0x0002
  865.                 from #t1 t, sysreferences r, sysobjects o
  866.                 where t.bDone is null and r.fkeyid = t.pid and r.rkeyid = o.id
  867.  
  868.         end
  869.  
  870.         /*
  871.          * We have this generation of parents in #t2, so clear the current
  872.          * child generation's bDone flags.  Then insert from #t2; the current
  873.          * parent generation becomes the next loop's child generation, with
  874.          * bDone = null until next loop's dependencies are selected.
  875.          */
  876.         update #t1 set bDone = 1
  877.         insert #t1 select * from #t2 where #t2.tid not in
  878.             (select tid from #t1 where #t1.tid = #t2.tid and #t1.pid = #t2.pid)
  879.         truncate table #t2
  880.  
  881.         /* If they only want one level, we're done.    */
  882.         if (@flags & 0x100000 <> 0)
  883.             update #t1 set bDone = 1
  884.     end
  885.  
  886.     /*
  887.      * The inner loop above did not put parents with no parents into the
  888.      * child (tid) list.  Do that now, then remove all rows where tid is
  889.      * NULL, because these were initial objects which now have a tid row.
  890.      * Just in case, remove self-refs from #t1, and also remove rows from #t1
  891.      * with NULL pid if a row exists for that tid where the pid is nonNULL.
  892.      * Avoid nested self-joins by using worktables.
  893.      */
  894.  
  895.     truncate table #t3
  896.     insert #t3 select tid from #t1 where tid is not null
  897.     update statistics #t3 #ci_t3
  898.     insert #t1 (tid, ttype, tcat, bDone) select distinct pid, ptype, pcat, 0 from #t1 t
  899.         where t.pid is not null and not exists (select * from #t3 where tid = t.pid)
  900.  
  901.  
  902.  
  903.  
  904.  
  905.     /*
  906.      * Because triggers can go in both directions, we'll need to check for
  907.      * circular dependencies on parent evaluation.  Since any tables referenced
  908.      * by the trigger must exist before the trigger can be created, remove rows
  909.      * where the trigger is the parent.
  910.      */
  911.     if (@flags & 0x40000 = 0)
  912.         delete #t1 where ptype = 8
  913.  
  914.  
  915.     truncate table #t3
  916.     insert #t3 select tid from #t1 where tid is not null and pid is not null
  917.     update statistics #t3 #ci_t3
  918.     delete #t1 where #t1.tid is null or #t1.tid = #t1.pid 
  919.         or (#t1.pid is null and exists (select * from #t3 where tid = #t1.tid))
  920.  
  921.  
  922.  
  923.  
  924.  
  925.     /*
  926.      * If we're to get all objects, get all UDDTs (which aren't in sysobjects)
  927.      * and Rules/Defaults, assuming we're returning those types.
  928.      */
  929.     if (@allobjs <> 0)
  930.     begin
  931.         if (@flags & power(2, 0) != 0)
  932.             insert #tempudt
  933.                 select usertype from systypes where usertype > 99
  934.         if (@flags & (power(2, 7) | power(2, 6)) != 0)
  935.             insert #t2 (tid, ttype, tcat)
  936.                 select id, sysstat & 0x0f, 0 from sysobjects
  937.                 where sysstat in (7, 6)
  938.                 and category & 0x0800 = 0
  939.     end else begin
  940.         /*
  941.          * Not getting all objects.  Get any datatypes that
  942.          * are referenced by objects in #t1.  We don't care about specific
  943.          * datatype dependencies, we just want to know which ones are needed.
  944.          */
  945.         if (@flags & power(2, 0) != 0)
  946.             insert #tempudt select distinct usertype from syscolumns
  947.                 where usertype > 99 and id in (select tid from #t1)
  948.  
  949.         /*
  950.          * Load rules and defaults needed by datatypes and other #t1 objects
  951.          * into #t2.  Don't track specific object dependencies with these;
  952.          * we just want to know which ones are needed.  For defaults only, eliminate
  953.          * those which are constraints.
  954.          */
  955.         if (@flags & power(2, 7) != 0)
  956.         begin
  957.             insert #t2 (tid, ttype, tcat)
  958.                 select distinct s.domain, 7, 0 from systypes s, #tempudt t
  959.                     where s.domain != 0 and s.usertype = t.dtype
  960.                         and s.domain not in (select tid from #t1)
  961.             insert #t2 (tid, ttype, tcat)
  962.                 select distinct s.domain, 7, 0 from syscolumns s, #t1 t
  963.                     where s.domain != 0 and s.id = t.tid
  964.                         and s.domain not in (select tid from #t1)
  965.         end
  966.         if (@flags & power(2, 6) != 0)
  967.         begin
  968.             insert #t2 (tid, ttype, tcat)
  969.                 select distinct s.tdefault, 6, 0 from systypes s, #tempudt t
  970.                     where s.tdefault != 0 and s.usertype = t.dtype
  971.                         and s.tdefault not in (select tid from #t1)
  972.                         and s.tdefault not in (select id from sysobjects where category & 0x0800 != 0)
  973.             insert #t2 (tid, ttype, tcat)
  974.                 select distinct s.cdefault, 6, 0 from syscolumns s, #t1 t
  975.                     where s.cdefault != 0 and s.id = t.tid
  976.                         and s.cdefault not in (select tid from #t1)
  977.                         and s.cdefault not in (select id from sysobjects where category & 0x0800 != 0)
  978.         end
  979.     end        /* Not getting all objects */
  980.  
  981.     /*
  982.      * Now that we've got all objects we want, eliminate those we don't
  983.      * want to return.  If @inputobj and they don't want it returned,
  984.      * remove it from the table.  Then eliminate object types they don't
  985.      * want returned.  Make sure that in doing so we retain all parent
  986.      * objects of the types we do want -- it is possible at this point
  987.      * that a tid we want has no rows except those with pids we don't want.
  988.      */
  989.     if (@flags & 0x01ff != 0x01ff or @delinputobj != 0)
  990.     begin
  991.         delete #t1 where @flags & power(2, ttype) = 0 or tid = @delinputobj
  992.  
  993.         /*
  994.          * Be sure that the insert does not duplicate rows that will survive the
  995.          * following delete -- these are rows where the pid is not @delinputobj
  996.          * and ptype is either null or a type we'll keep (if ptype is null then
  997.          * pid hasn't been set so no need for more complex checking).
  998.          */
  999.         insert #t1 (tid, ttype, tcat) select distinct tid, ttype, tcat from #t1
  1000.             where (@flags & power(2, ptype) = 0 or pid = @delinputobj)
  1001.                 and tid not in (select tid from #t1 where ptype is null or
  1002.                     (pid != @delinputobj and @flags & power(2, ptype) != 0))
  1003.         delete #t1 where @flags & power(2, ptype) = 0 or pid = @delinputobj
  1004.     end
  1005.  
  1006.     /*
  1007.      * To determine creation order, find all objects which are not yet bDone
  1008.      * and have no parents or whose parents are all bDone, and set their bDone
  1009.      * to the next @curid.  This will leave bDone as the ascending order in
  1010.      * which objects must be created (topological sort).  Again, use worktables
  1011.      * to remove nested self-joins.
  1012.      */
  1013.     update #t1 set bDone = 0
  1014.     select @curid = 1, @rowsaffected = 1
  1015.     while (@rowsaffected <> 0)
  1016.     begin
  1017.  
  1018.         if (@flags & 0x40000 != 0) begin
  1019.             truncate table #t3
  1020.             insert #t3 select pid from #t1 where pid is not null and bDone = 0
  1021.             update statistics #t3 #ci_t3
  1022.             update #t1 set bDone = @curid where bDone = 0 and tid not in (select tid from #t3)
  1023.         end else begin
  1024.             truncate table #t3
  1025.             truncate table #t4
  1026.             insert #t3 select tid from #t1 where bDone = 0                /* Parents not yet done */
  1027.             update statistics #t3 #ci_t3
  1028.             insert #t4 select tid from #t1                                /* TIDs with (parents not yet done) */
  1029.                 where pid is not null and pid in (select tid from #t3)
  1030.             update statistics #t4 #ci_t4
  1031.             update #t1 set #t1.bDone = @curid where #t1.bDone = 0         /* TIDs who are not (TIDs with (parents not yet done)) */
  1032.                 and not exists (select * from #t4 where tid = #t1.tid)
  1033.         end
  1034.  
  1035.  
  1036.  
  1037.  
  1038.  
  1039.  
  1040.  
  1041.  
  1042.  
  1043.         select @rowsaffected = @@rowcount, @curid = @curid + 1
  1044.     end
  1045.  
  1046.     /* For SQL60 only, we need to check circular dependencies (DRI for tables is the only way to get them). */
  1047.     /* This will have occurred if we still have any rows in #t1 where bDone = 0, after the above loop. */
  1048.  
  1049.     if exists (select * from #t1 where bDone = 0) begin
  1050.         RAISERROR (14300, -1, -1)
  1051.         return 1
  1052.     end
  1053.  
  1054.  
  1055.     /*
  1056.      * Finally, return the objects.  Rules/Defaults must be created first so they're returned first,
  1057.      * followed by UDDTs. followed by all other (sysdepends/DRI) dependencies.  @curid is the bDone
  1058.      * value; we need to increment the #t1 value so our multi-result-set is in the proper sequence.
  1059.      * Of course, these never have parents, so don't return them if asking for children.
  1060.      */
  1061.     if (@flags & 0x40000 = 0) begin
  1062.         select @curid = 1
  1063.         if ((@flags & (power(2, 7) | power(2, 6)) != 0) and exists (select * from #t2)) begin
  1064.             update #t1 set bDone = bDone + 1
  1065.             select distinct oType = power(2, o.sysstat & 0x0f), oRuleDefName = o.name, oOwner = user_name(o.uid), oSequence = convert(smallint, @curid)
  1066.                 from sysobjects o, #t2 t
  1067.                 where o.id = t.tid
  1068.                 order by power(2, o.sysstat & 0x0f), o.name
  1069.             select @curid = @curid + 1
  1070.         end
  1071.         if ((@flags & power(2, 0) != 0) and exists (select * from #tempudt)) begin
  1072.             update #t1 set bDone = bDone + 1
  1073.             select distinct oType = power(2, 0), oUDDTName = c.name, oOwner = user_name(c.uid), oSequence = convert(smallint, @curid)
  1074.                 from systypes c, #tempudt t, sysobjects p
  1075.                 where c.usertype = t.dtype
  1076.                 order by c.name
  1077.             select @curid = @curid + 1
  1078.         end
  1079.     end
  1080.  
  1081.     /*
  1082.      * Select dependency-style objects, returning parents if desired.
  1083.      * Normally sorting is in terms of who must be created first, i.e. ascending:  parent-->child-->grandchild.
  1084.      * Descending order (child-->parent-->grandparent) would be used for a graphical-dependencies evaluator showing
  1085.      * the parents.  Therefore we invert bDone if descending sort.  bDone is 1-based; min + max - bDone gives inversion.
  1086.      * Note:  Always return at least this empty set.
  1087.      */
  1088.     if (@flags & 0x20000 != 0) begin
  1089.         select @curid = max(bDone) + min(bDone) from #t1
  1090.         update #t1 set bDone = convert(smallint, @curid) - bDone
  1091.     end
  1092.     if (@flags & 0x10000 != 0)
  1093.         select distinct oType = power(2, o.sysstat & 0x0f), oObjName = o.name, oOwner = user_name(o.uid),
  1094.                 RelType = power(2, p.sysstat & 0x0f), RelName = p.name, RelOwner = user_name(p.uid),
  1095.                 oSequence = t.bDone
  1096.             from sysobjects o, sysobjects p, #t1 t
  1097.             where o.id = t.tid and p.id =* t.pid
  1098.             order by t.bDone, power(2, o.sysstat & 0x0f), o.name
  1099.     else
  1100.         select distinct oType = power(2, o.sysstat & 0x0f), oObjName = o.name, oOwner = user_name(o.uid),
  1101.                 oSequence = t.bDone
  1102.             from sysobjects o, #t1 t
  1103.             where o.id = t.tid
  1104.             order by t.bDone, power(2, o.sysstat & 0x0f), o.name
  1105. go
  1106. /* End sp_MSdependencies */
  1107.  
  1108. /************* DUMP THE TRANSACTION LOG **************************************/
  1109. /* Comment this out if you don't want your log dumped.  If you rerun this    */
  1110. /* script periodically, you will run out of transaction log space.           */
  1111. print ''
  1112. print 'Dumping transaction log...'
  1113. print ''
  1114. go
  1115. dump tran master with no_log
  1116. go
  1117. /************* END DUMP THE TRANSACTION LOG **********************************/
  1118.  
  1119. /*******************************************************************************/
  1120. print ''
  1121. print 'Creating sp_MStablespace'
  1122. print ''
  1123. go
  1124.  
  1125. create procedure sp_MStablespace
  1126. @name varchar(92), @id int = null
  1127. as
  1128.     declare @rows int, @datasizeused int, @indexsizeused int, @pagesize int
  1129.     declare @dbname varchar(30)
  1130.     select @dbname = db_name()
  1131.     
  1132.  
  1133.     if (@id is null)
  1134.         select @id = id from sysobjects where id = object_id(@name) and sysstat & 0x0f in (1, 3)
  1135.     if (@id is null)
  1136.     begin
  1137.         
  1138.         RAISERROR (15009, -1, -1, @name, @dbname)
  1139.         return 1
  1140.     end
  1141.  
  1142.     /* rows */
  1143.     SELECT @rows = rows
  1144.         FROM sysindexes
  1145.         WHERE indid < 2 and id = @id
  1146.  
  1147.     /* data */
  1148.     SELECT @datasizeused =
  1149.     (SELECT sum(dpages)
  1150.      FROM sysindexes
  1151.      WHERE indid < 2 and id = @id)
  1152.     +
  1153.     (SELECT isnull(sum(used), 0)
  1154.      FROM sysindexes
  1155.      WHERE indid = 255 and id = @id)
  1156.  
  1157.     /* index */
  1158.     SELECT @indexsizeused =
  1159.     (SELECT sum(used)
  1160.      FROM sysindexes
  1161.      WHERE indid in (0, 1, 255) and id = @id)
  1162.      - @datasizeused
  1163.  
  1164.     /* Pagesize on this server (sysindexes stores size info in pages) */
  1165.     select @pagesize = v.low / 1024 from master..spt_values v where v.number=1 and v.type='E'
  1166.  
  1167.     select Rows = @rows, DataSpaceUsed = @datasizeused * @pagesize, IndexSpaceUsed = @indexsizeused    * @pagesize
  1168. go
  1169.  
  1170. /* End sp_MStablespace */
  1171.  
  1172. /*******************************************************************************/
  1173. print ''
  1174. print 'Creating sp_MSindexspace'
  1175. print ''
  1176. go
  1177.  
  1178. CREATE PROCEDURE sp_MSindexspace
  1179.     @tablename varchar(92), @index_name varchar(30) = NULL
  1180. AS
  1181. BEGIN
  1182.   DECLARE @table_id int
  1183.   DECLARE @index_id int
  1184.   DECLARE @msg varchar(255)
  1185.   
  1186.  
  1187.   /* Make sure @tablename is local to the current database */
  1188.   IF (@tablename like '%.%.%') AND
  1189.      (substring(@tablename, 1, charindex('.', @tablename) - 1) <> db_name())
  1190.   BEGIN
  1191.     
  1192.     RAISERROR (15078, -1, -1, '')
  1193.     RETURN(1)
  1194.   END
  1195.   /* Make sure that @tablename and @index_name exist */
  1196.   SELECT @table_id = id
  1197.   FROM sysobjects
  1198.   WHERE (id = object_id(@tablename))
  1199.     AND (sysstat & 0xf = 3)
  1200.   IF (@table_id = NULL)
  1201.   BEGIN
  1202.     
  1203.     RAISERROR (15001, -1, -1, @tablename)
  1204.     RETURN(1)
  1205.   END
  1206.   IF (@index_name <> NULL)
  1207.   BEGIN
  1208.     SELECT @index_id = indid
  1209.     FROM sysindexes
  1210.     WHERE (name = @index_name)
  1211.       AND (id = object_id(@tablename))
  1212.     IF (@index_id = NULL)
  1213.     BEGIN
  1214.       SELECT @msg = @tablename + '.' + @index_name
  1215.       
  1216.       RAISERROR (15001, -1, -1, @msg)
  1217.       RETURN(1)
  1218.     END
  1219.   END
  1220.   /* Ok, we're good to go */
  1221.   IF (user_id() = 1) 
  1222.     CHECKPOINT
  1223.   IF (@index_name = NULL)
  1224.   BEGIN
  1225.     CREATE TABLE #IndexSizeTemp
  1226.     (IndexID tinyint, IndexName varchar(30), IndexSize int, Comments varchar(28))  
  1227.     INSERT INTO #IndexSizeTemp
  1228.     SELECT indid, name, 0, ''
  1229.     FROM sysindexes 
  1230.     WHERE (id = object_id(@tablename))
  1231.       AND ((indid > 0) AND (indid < 255)) 
  1232.     UPDATE #IndexSizeTemp
  1233.     SET IndexSize = used * 2,
  1234.         Comments = '(None)' 
  1235.     FROM sysindexes si, #IndexSizeTemp ist
  1236.     WHERE (id = object_id(@tablename))
  1237.       AND (indid > 1) AND (indid < 255)
  1238.       AND (si.indid = ist.IndexID)
  1239.     UPDATE #IndexSizeTemp
  1240.     SET IndexSize = (used - dpages - isnull((SELECT sum(used) 
  1241.                                              FROM sysindexes
  1242.                                              WHERE (indid > 1) AND (indid < 255) 
  1243.                                                AND (id = object_id(@tablename))), 0)) * 2,
  1244.         Comments = 'Size excludes actual data.' 
  1245.     FROM sysindexes si, #IndexSizeTemp ist
  1246.     WHERE (id = object_id(@tablename))
  1247.       AND (indid = 1)
  1248.       AND (si.indid = ist.IndexID)
  1249.     SELECT 'Index ID' = IndexID, 'Index Name' = IndexName, 'Size (KB)' = IndexSize, Comments 
  1250.     FROM #IndexSizeTemp
  1251.     ORDER BY IndexID
  1252.     DROP TABLE #IndexSizeTemp
  1253.   END
  1254.   ELSE
  1255.   BEGIN 
  1256.     DECLARE @indid int
  1257.     SELECT @indid = indid 
  1258.     FROM sysindexes 
  1259.     WHERE (id = object_id(@tablename))
  1260.       AND (name = @index_name)
  1261.     /* The non-clustered index case */
  1262.     IF ((@indid > 1) AND (@indid < 255))
  1263.     BEGIN
  1264.       SELECT 'Size (KB)' = used * 2 
  1265.       FROM sysindexes 
  1266.       WHERE (id = object_id(@tablename))
  1267.         AND (name = @index_name)
  1268.       RETURN(0) 
  1269.     END
  1270.     /* The clustered index case */
  1271.     IF (@indid = 1)
  1272.     BEGIN
  1273.       SELECT 'Size (KB)' =
  1274.              (used - dpages - isnull((SELECT sum(used) 
  1275.                                       FROM sysindexes
  1276.                                       WHERE (indid > 1) AND (indid < 255) 
  1277.                                         AND (id = object_id(@tablename))), 0)) * 2 
  1278.       FROM sysindexes 
  1279.       WHERE (id = object_id(@tablename))
  1280.         AND (name = @index_name)
  1281.     END
  1282.   END
  1283.   RETURN(0)
  1284. END
  1285. go
  1286. /* End sp_MSindexspace */
  1287.  
  1288. /*******************************************************************************/
  1289.  
  1290. print ''
  1291. print 'Creating sp_MStablekeys'
  1292. print ''
  1293. go
  1294.  
  1295. create procedure sp_MStablekeys
  1296. @tablename varchar(92) = null, @colname varchar(30) = null, @type int = 0x00e, @keyname varchar(30) = null
  1297. as
  1298.     /* This proc returns the table's DRI keys.  @type is the type(s) of key(s) to return. */
  1299.     /* Make sure @type is only the key types (DRI_PRIMARYKEY, DRI_UNIQUE, DRI_REFERENCE). */
  1300.     select @type = @type & 0x000e
  1301.  
  1302.     set nocount on
  1303.     create table #spkeys
  1304.     (
  1305.         cType                tinyint,            /* key Type */
  1306.         cName                varchar(30),        /* key Name */
  1307.         cFlags                int NULL,            /* e.g., 1 = clustered for PK/Unique */
  1308.         cColCount            int NULL,            /* number of columns (or column pairs) in the key */
  1309.         cFillFactor            tinyint NULL,        /* Fill factor of index creation */
  1310.         cRefTable            varchar(64) NULL,    /* owner-qual Referenced table name for FKs */
  1311.         cRefKey                varchar(32) NULL,    /* name of referenced key in referenced table */
  1312.         cKeyCol1            varchar(32) NULL,    /* key column names */
  1313.         cKeyCol2            varchar(32) NULL,    /* key column names */
  1314.         cKeyCol3            varchar(32) NULL,    /* key column names */
  1315.         cKeyCol4            varchar(32) NULL,    /* key column names */
  1316.         cKeyCol5            varchar(32) NULL,    /* key column names */
  1317.         cKeyCol6            varchar(32) NULL,    /* key column names */
  1318.         cKeyCol7            varchar(32) NULL,    /* key column names */
  1319.         cKeyCol8            varchar(32) NULL,    /* key column names */
  1320.         cKeyCol9            varchar(32) NULL,    /* key column names */
  1321.         cKeyCol10            varchar(32) NULL,    /* key column names */
  1322.         cKeyCol11            varchar(32) NULL,    /* key column names */
  1323.         cKeyCol12            varchar(32) NULL,    /* key column names */
  1324.         cKeyCol13            varchar(32) NULL,    /* key column names */
  1325.         cKeyCol14            varchar(32) NULL,    /* key column names */
  1326.         cKeyCol15            varchar(32) NULL,    /* key column names */
  1327.         cKeyCol16            varchar(32) NULL,    /* key column names */
  1328.         cRefCol1            varchar(32) NULL,    /* referenced column names */
  1329.         cRefCol2            varchar(32) NULL,    /* referenced column names */
  1330.         cRefCol3            varchar(32) NULL,    /* referenced column names */
  1331.         cRefCol4            varchar(32) NULL,    /* referenced column names */
  1332.         cRefCol5            varchar(32) NULL,    /* referenced column names */
  1333.         cRefCol6            varchar(32) NULL,    /* referenced column names */
  1334.         cRefCol7            varchar(32) NULL,    /* referenced column names */
  1335.         cRefCol8            varchar(32) NULL,    /* referenced column names */
  1336.         cRefCol9            varchar(32) NULL,    /* referenced column names */
  1337.         cRefCol10            varchar(32) NULL,    /* referenced column names */
  1338.         cRefCol11            varchar(32) NULL,    /* referenced column names */
  1339.         cRefCol12            varchar(32) NULL,    /* referenced column names */
  1340.         cRefCol13            varchar(32) NULL,    /* referenced column names */
  1341.         cRefCol14            varchar(32) NULL,    /* referenced column names */
  1342.         cRefCol15            varchar(32) NULL,    /* referenced column names */
  1343.         cRefCol16            varchar(32) NULL,    /* referenced column names */
  1344.         cIndexID            int    NULL            /* ID of this key's index, if PK/UQ */
  1345.     )
  1346.  
  1347.     declare @cType int, @cName varchar(30), @cFlags int, @cRefTable varchar(64), @fillfactor tinyint
  1348.     declare @objid int, @constid int, @indid int, @keycnt int, @q1 varchar(255), @q2 varchar(255)
  1349.  
  1350.     /* First see if @keyname was defined, and override @tablename and @type if so. */
  1351.     if (@keyname is not null)
  1352.     begin
  1353.         select @objid = id, @type = power(2, status & 0x0f) from sysconstraints where constid = object_id(@keyname)
  1354.         if (@objid is null)    begin
  1355.             RAISERROR (15001, -1, -1, @keyname)
  1356.             return 1
  1357.         end
  1358.         /* Now get the tablename for the index_col below */
  1359.         select @tablename = user_name(uid) + '.' + name from sysobjects where id = @objid
  1360.     end else begin
  1361.         /* Want all keys for this table (of @type type). */
  1362.         select @objid = object_id(@tablename)
  1363.         if (@objid is null)    begin
  1364.             RAISERROR (15001, -1, -1, @tablename)
  1365.             return 1
  1366.         end
  1367.         if exists (select id from sysobjects where id = @objid and sysstat & 0x0f not in (1, 3))    begin
  1368.             RAISERROR (15218, -1, -1, @tablename)
  1369.             return 1
  1370.         end
  1371.         if @colname is not null and not exists (select * from syscolumns where id = @objid and name = @colname) begin
  1372.             RAISERROR (15253, -1, -1, @colname, @tablename)
  1373.             return 1
  1374.         end
  1375.     end
  1376.  
  1377.     /* Preprocessor won't replace within quotes so have to use str(). */
  1378.     declare @sysgenname varchar(12), @pkstr varchar(12), @uqstr varchar(12), @fkstr varchar(12), @objtypebits varchar(12)
  1379.     select @sysgenname = ltrim(str(convert(int, 0x00020000)))
  1380.     select @pkstr = ltrim(str(convert(int, 1)))
  1381.     select @uqstr = ltrim(str(convert(int, 2)))
  1382.     select @fkstr = ltrim(str(convert(int, 3)))
  1383.     select @objtypebits = ltrim(str(convert(int, 0x0f)))
  1384.  
  1385.     /* Other ints we need strings for */
  1386.     declare @objidstr varchar(12), @typestr varchar(12)
  1387.     select @objidstr = ltrim(str(@objid))
  1388.     select @typestr = ltrim(str(@type))
  1389.  
  1390.     /* Qualifying key name. */
  1391.     declare @qualkeyname varchar(100)
  1392.     select @qualkeyname = null
  1393.     if (@keyname is not null)
  1394.         select @qualkeyname = ' and constid = object_id(''' + @keyname + ''')'
  1395.  
  1396.     /*********************/
  1397.     /* Main cursor loop. */
  1398.     /*********************/
  1399.     exec('declare hC insensitive cursor for select constid, status & ' + @objtypebits + ', status & ' + @sysgenname + 
  1400.             ' from sysconstraints where id = ' + @objidstr + ' and (' + @typestr + ' & power(2, status & 0x0f) != 0) ' + @qualkeyname)
  1401.     open hC
  1402.     fetch hC into @constid, @cType, @cFlags
  1403.     while (@@fetch_status >= 0) begin
  1404.         if (object_name(@constid) is null) begin
  1405.             raiserror 55555 'Assert failed:  object_name(@constid) is null in sp_MStablekeys (pk/uq)'
  1406.             return 1
  1407.         end
  1408.  
  1409.         /* DRI_PRIMARYKEY, DRI_UNIQUE */
  1410.         if (@cType in (1, 2)) begin
  1411.             /* Get the index id enforcing this constraint. */
  1412.             select @indid = i.indid, @cName = o.name, @fillfactor = i.OrigFillFactor,
  1413.                     @cFlags = @cFlags | (case indid when 1 then 0x00000001 else 0 end),        /* test for clustered index */
  1414.                     @keycnt = case indid when 1 then keycnt else keycnt - 1 end                    /* keycnt includes RID if nc index */
  1415.                 from sysindexes i, sysobjects o
  1416.                 where o.id = @constid and i.name = o.name and i.status & 0x1800 <> 0
  1417.             if (@indid is null) begin
  1418.                 raiserror 77777 "Assert failed:  @indid is null in sp_MStablekeys (pk/uq)"
  1419.                 return 1
  1420.             end
  1421.  
  1422.             /* Load our temp table. */
  1423.             insert #spkeys values (@cType, @cName, @cFlags, @keycnt, @fillfactor, null, null,
  1424.                 index_col(@tablename, @indid, 1), index_col(@tablename, @indid, 2),    index_col(@tablename, @indid, 3), index_col(@tablename, @indid, 4),
  1425.                 index_col(@tablename, @indid, 5), index_col(@tablename, @indid, 6),    index_col(@tablename, @indid, 7), index_col(@tablename, @indid, 8),
  1426.                 index_col(@tablename, @indid, 9), index_col(@tablename, @indid, 10),index_col(@tablename, @indid, 11), index_col(@tablename, @indid, 12),
  1427.                 index_col(@tablename, @indid, 13), index_col(@tablename, @indid, 14),    index_col(@tablename, @indid, 15), index_col(@tablename, @indid, 16),
  1428.                 null, null, null, null,    null, null, null, null,    null, null, null, null,    null, null, null, null, @indid)
  1429.         end
  1430.  
  1431.         /* DRI_REFERENCE */
  1432.         else if (@cType in (3)) begin
  1433.             /* Get the key column information from sysreferences. */
  1434.             select @keycnt = r.keycnt, @cName = object_name(r.constid), @cRefTable = user_name(o.uid) + '.' + o.name
  1435.                 from sysreferences r, sysobjects o where r.constid = @constid and o.id = r.rkeyid
  1436.  
  1437.             /* Follow r.rkeyindid back to sysindexes to get the ref key name. */
  1438.             declare @cRefKey varchar(32)
  1439.             select @cRefKey = i.name, @cFlags = c.status from sysreferences r, sysindexes i, sysconstraints c
  1440.                 where c.constid = r.constid and r.constid = @constid
  1441.                 and i.id = r.rkeyid and i.indid = r.rkeyindid and i.status & 0x1800 <> 0
  1442.  
  1443.             /* Load our temp table. */
  1444.             insert #spkeys select @cType, @cName, @cFlags, @keycnt, null, @cRefTable, @cRefKey,
  1445.                 col_name(r.fkeyid, r.fkey1), col_name(r.fkeyid, r.fkey2), col_name(r.fkeyid, r.fkey3), col_name(r.fkeyid, r.fkey4),
  1446.                 col_name(r.fkeyid, r.fkey5), col_name(r.fkeyid, r.fkey6), col_name(r.fkeyid, r.fkey7), col_name(r.fkeyid, r.fkey8),
  1447.                 col_name(r.fkeyid, r.fkey9), col_name(r.fkeyid, r.fkey10),col_name(r.fkeyid, r.fkey11), col_name(r.fkeyid, r.fkey12),
  1448.                 col_name(r.fkeyid, r.fkey13), col_name(r.fkeyid, r.fkey14),col_name(r.fkeyid, r.fkey15), col_name(r.fkeyid, r.fkey16),
  1449.                 col_name(r.rkeyid, r.rkey1), col_name(r.rkeyid, r.rkey2),    col_name(r.rkeyid, r.rkey3), col_name(r.rkeyid, r.rkey4),
  1450.                 col_name(r.rkeyid, r.rkey5), col_name(r.rkeyid, r.rkey6), col_name(r.rkeyid, r.rkey7), col_name(r.rkeyid, r.rkey8),
  1451.                 col_name(r.rkeyid, r.rkey9), col_name(r.rkeyid, r.rkey10), col_name(r.rkeyid, r.rkey11), col_name(r.rkeyid, r.rkey12),
  1452.                 col_name(r.rkeyid, r.rkey13), col_name(r.rkeyid, r.rkey14), col_name(r.rkeyid, r.rkey15), col_name(r.rkeyid, r.rkey16),
  1453.                 null
  1454.             from sysreferences r where r.constid = @constid
  1455.         end        /* Key type */
  1456.  
  1457.         /* Get the next row. */
  1458.         fetch hC into @constid, @cType, @cFlags
  1459.     end            /* PRIMARY/UNIQUE */
  1460.     deallocate hC
  1461.  
  1462.     /* Now output the data */
  1463.     set nocount off
  1464.     if @colname is null
  1465.         select * from #spkeys order by cType, cName
  1466.     else
  1467.         select * from #spkeys where
  1468.             cKeyCol1 = @colname or cKeyCol2 = @colname or cKeyCol3 = @colname or cKeyCol3 = @colname or
  1469.             cKeyCol5 = @colname or cKeyCol6 = @colname or cKeyCol7 = @colname or cKeyCol8 = @colname or
  1470.             cKeyCol9 = @colname or cKeyCol10 = @colname or cKeyCol11 = @colname or cKeyCol12 = @colname or
  1471.             cKeyCol13 = @colname or cKeyCol14 = @colname or cKeyCol15 = @colname or cKeyCol16 = @colname
  1472.          order by cType, cName
  1473. go
  1474. /* End sp_MStablekeys */
  1475.  
  1476. /*-- Another SQL60-only proc ---------------------------------------------------*/
  1477. print ''
  1478. print 'Creating sp_MSgetalertinfo'
  1479. print ''
  1480. go
  1481. create procedure sp_MSgetalertinfo
  1482.     @includeaddresses bit = 0
  1483. as
  1484.     /* Return all alert info at one go, for performance reasons. */
  1485.     declare @FailSafeOperator varchar(255)
  1486.     declare @NotificationMethod int
  1487.     declare @ForwardingServer varchar(255)
  1488.     declare @ForwardingSeverity int
  1489.     declare @PagerToTemplate varchar(255)
  1490.     declare @PagerCCTemplate varchar(255)
  1491.     declare @PagerSubjectTemplate varchar(255)
  1492.     declare @PagerSendSubjectOnly int
  1493.     declare @FailSafeEmailAddress varchar(255)
  1494.     declare @FailSafePagerAddress varchar(255)
  1495.  
  1496.     exec master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertFailSafeOperator', @param = @FailSafeOperator OUT
  1497.     exec master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertNotificationMethod', @param = @NotificationMethod OUT
  1498.     exec master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertForwardingServer', @param = @ForwardingServer OUT
  1499.     exec master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertForwardingSeverity', @param = @ForwardingSeverity OUT
  1500.     exec master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertPagerToTemplate', @param = @PagerToTemplate OUT
  1501.     exec master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertPagerCCTemplate', @param = @PagerCCTemplate OUT
  1502.     exec master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertPagerSubjectTemplate', @param = @PagerSubjectTemplate OUT
  1503.     exec master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertPagerSendSubjectOnly', @param = @PagerSendSubjectOnly OUT
  1504.  
  1505.     if (@includeaddresses <> 0) begin
  1506.         exec master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertFailSafeEmailAddress', @param = @FailSafeEmailAddress OUT
  1507.         exec master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertFailSafePagerAddress', @param = @FailSafePagerAddress OUT
  1508.     end
  1509.  
  1510.     select
  1511.         AlertFailSafeOperator = @FailSafeOperator,
  1512.         AlertNotificationMethod = @NotificationMethod,
  1513.         AlertForwardingServer = @ForwardingServer,
  1514.         AlertForwardingSeverity = @ForwardingSeverity,
  1515.         AlertPagerToTemplate = @PagerToTemplate,
  1516.         AlertPagerCCTemplate = @PagerCCTemplate,
  1517.         AlertPagerSubjectTemplate = @PagerSubjectTemplate,
  1518.         AlertPagerSendSubjectOnly = @PagerSendSubjectOnly
  1519.  
  1520.     if (@includeaddresses <> 0) 
  1521.         select
  1522.             AlertFailSafeEmailAddress = @FailSafeEmailAddress,
  1523.             AlertFailSafePagerAddress = @FailSafePagerAddress
  1524. go
  1525. /* End sp_MSgetalertinfo */
  1526.  
  1527. /*-- Another SQL60-only proc ---------------------------------------------------*/
  1528. print ''
  1529. print 'Creating sp_MSsetalertinfo'
  1530. print ''
  1531. go
  1532. create procedure sp_MSsetalertinfo
  1533.     @failsafeoperator varchar(255) = null,
  1534.     @notificationmethod int = null,
  1535.     @forwardingserver varchar(255) = null,
  1536.     @forwardingseverity int = null,
  1537.     @pagertotemplate varchar(255) = null,
  1538.     @pagercctemplate varchar(255) = null,
  1539.     @pagersubjecttemplate varchar(255) = null,
  1540.     @pagersendsubjectonly int = null,
  1541.     @failsafeemailaddress varchar(255) = null,
  1542.     @failsafepageraddress varchar(255) = null
  1543. as
  1544.     /* Set all alert info at one go, for performance reasons.  Translate values if needed. */
  1545.     if (@pagersendsubjectonly is not null and @pagersendsubjectonly <> 0)
  1546.         select @pagersendsubjectonly = 1
  1547.  
  1548.     if (@failsafeoperator is not null)
  1549.         exec master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertFailSafeOperator', 'REG_SZ', @failsafeoperator
  1550.     if (@notificationmethod is not null)
  1551.         exec master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertNotificationMethod', 'REG_DWORD', @notificationmethod
  1552.     if (@forwardingserver is not null)
  1553.         exec master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertForwardingServer', 'REG_SZ', @forwardingserver
  1554.     if (@forwardingseverity is not null)
  1555.         exec master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertForwardingSeverity', 'REG_DWORD', @forwardingseverity
  1556.     if (@pagertotemplate is not null)
  1557.         exec master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertPagerToTemplate', 'REG_SZ', @pagertotemplate
  1558.     if (@pagercctemplate is not null)
  1559.         exec master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertPagerCCTemplate', 'REG_SZ', @pagercctemplate
  1560.     if (@pagersubjecttemplate is not null)
  1561.         exec master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertPagerSubjectTemplate', 'REG_SZ', @pagersubjecttemplate
  1562.     if (@pagersendsubjectonly is not null)
  1563.         exec master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertPagerSendSubjectOnly', 'REG_DWORD', @pagersendsubjectonly
  1564.     if (@failsafeemailaddress is not null)
  1565.         exec master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertFailSafeEmailAddress', 'REG_SZ', @failsafeemailaddress
  1566.     if (@failsafepageraddress is not null)
  1567.         exec master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'AlertFailSafePagerAddress', 'REG_SZ', @failsafepageraddress
  1568. go
  1569. /* End sp_MSgetalertinfo */
  1570.  
  1571. /*-- Another SQL60-only proc ---------------------------------------------------*/
  1572. print ''
  1573. print 'Creating sp_MSgetexecinfo'
  1574. print ''
  1575. go
  1576. create procedure sp_MSgetexecinfo
  1577.     @includeaddresses bit = 0
  1578. as
  1579.     /* Return all SQLExecutive info at one go, for performance reasons. */
  1580.     declare @AutoStart int
  1581.     declare @RestartSQLServer int
  1582.     declare @RestartSQLServerInterval int
  1583.     declare @LimitHistoryRows int
  1584.     declare @LimitHistoryRowsMax int
  1585.  
  1586.     exec master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', 'SYSTEM\CurrentControlSet\Services\SQLExecutive', 'Start', @param = @AutoStart OUT
  1587.     exec master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'RestartSQLServer', @param = @RestartSQLServer OUT
  1588.     exec master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'RestartSQLServerInterval', @param = @RestartSQLServerInterval OUT
  1589.     exec master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'SyshistoryLimitRows', @param = @LimitHistoryRows OUT
  1590.     exec master.dbo.xp_regread 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'SyshistoryMaxRows', @param = @LimitHistoryRowsMax OUT
  1591.  
  1592.     /* Remember that for the Services, 2 == AutoStart, 3 == don't (don't ask me why). */
  1593.     select
  1594.         AutoStart = case when (2 = @AutoStart) then 1 else 0 end,
  1595.         RestartSQLServer = @RestartSQLServer,
  1596.         RestartSQLServerInterval = @RestartSQLServerInterval,
  1597.         LimitHistoryRows = @LimitHistoryRows,
  1598.         LimitHistoryRowsMax = @LimitHistoryRowsMax
  1599. go
  1600. /* End sp_MSgetexecinfo */
  1601.  
  1602. /*-- Another SQL60-only proc ---------------------------------------------------*/
  1603. print ''
  1604. print 'Creating sp_MSsetexecinfo'
  1605. print ''
  1606. go
  1607. create procedure sp_MSsetexecinfo
  1608.     @autostart int = null,
  1609.     @restartsqlserver int = null,
  1610.     @restartsqlserverinterval int = null,
  1611.     @limithistoryrows int = null,
  1612.     @limithistoryrowsmax int = null
  1613. as
  1614.     /* Set all SQLExecutive info at one go, for performance reasons.  Translate values if needed. */
  1615.     /* Remember that for the Services, 2 == AutoStart, 3 == don't (don't ask me why). */
  1616.     if (@autostart is not null)
  1617.         select @autostart = case when (0 = @autostart) then 3 else 2 end
  1618.     if (@restartsqlserver is not null and @restartsqlserver <> 0)
  1619.         select @restartsqlserver = 1
  1620.     if (@limithistoryrows is not null and @limithistoryrows <> 0)
  1621.         select @limithistoryrows = 1
  1622.  
  1623.     if (@autostart is not null)
  1624.         exec master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', 'SYSTEM\CurrentControlSet\Services\SQLExecutive', 'Start', 'REG_DWORD', @autostart
  1625.     if (@restartsqlserver is not null)
  1626.         exec master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'RestartSQLServer', 'REG_DWORD', @restartsqlserver
  1627.     if (@restartsqlserverinterval is not null)
  1628.         exec master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'RestartSQLServerInterval', 'REG_DWORD', @restartsqlserverinterval
  1629.     if (@limithistoryrows is not null)
  1630.         exec master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'SyshistoryLimitRows', 'REG_DWORD', @limithistoryrows
  1631.     if (@limithistoryrowsmax is not null)
  1632.         exec master.dbo.xp_regwrite 'HKEY_LOCAL_MACHINE', 'SOFTWARE\Microsoft\MSSQLServer\SQLExecutive', 'SyshistoryMaxRows', 'REG_DWORD', @limithistoryrowsmax
  1633. go
  1634. /* End sp_MSgetexecinfo */
  1635.  
  1636. /*-- Another SQL60-only proc ---------------------------------------------------*/
  1637. print ''
  1638. print 'Creating sp_MStablechecks'
  1639. print ''
  1640. go
  1641.  
  1642. create procedure sp_MStablechecks
  1643.     @tablename varchar(92)
  1644. as
  1645.     declare @id int
  1646.     select @id = object_id(@tablename)
  1647.     if (@id is null) begin
  1648.         RAISERROR (15001, -1, -1, @tablename)
  1649.         return 1
  1650.     end
  1651.  
  1652.     /* We'll put out the check text if it's all in one row (most likely); otherwise leave it */
  1653.     /* blank for refetching in its entirety via sp_helptext. */
  1654.     select distinct object_name(t.id), (select y.text from syscomments y where y.id = t.id and 
  1655.                                         1 = (select count(*) from syscomments where id = y.id)),
  1656.                 c.status & (convert(int, 0x00200000) | convert(int, 0x00020000))
  1657.     from syscomments t, sysconstraints c
  1658.     where t.id in (select constid from sysconstraints where id = @id and status & 0x0f = 4)
  1659.         and t.id = c.constid
  1660. go
  1661. /* End sp_MStablechecks */
  1662.  
  1663. /*-- Another SQL60-only proc ---------------------------------------------------*/
  1664. print ''
  1665. print 'Creating sp_MStablerefs'
  1666. print ''
  1667. go
  1668.  
  1669. create procedure sp_MStablerefs
  1670.     @tablename varchar(92),                    /* table whose references are being evaluated */
  1671.     @type varchar(20) = 'actualtables',        /* '[actual | all][tables | keys]'; all candidates, or only those actually referenced */
  1672.     @direction varchar(20) = 'primary',        /* look for references to 'primary' or from 'foreign' */
  1673.     @reftable varchar(92) = null            /* limit scope to this table, if non-null */
  1674. as
  1675.     if (@tablename = '?') begin
  1676.         PRINT ''
  1677.         PRINT 'sp_MStablerefs:'
  1678.         PRINT '@tablename varchar(92),                    /* table whose references are being evaluated */'
  1679.         PRINT '@type varchar(92) = [actualtables],        /* [[actual | all][tables | keys]]; all candidates, or only those actually referenced */'
  1680.         PRINT '@direction varchar(20) = [primary],        /* look for references to [primary] or from [foreign] */'
  1681.         PRINT '@reftable varchar(92) = null                /* limit scope to this table, if non-null */'
  1682.         return 0
  1683.     end
  1684.  
  1685.     declare @id int, @refid int
  1686.     select @id = object_id(@tablename), @refid = object_id(@reftable)
  1687.     if (@tablename is not null and @id is null) begin
  1688.         RAISERROR (15001, -1, -1, @tablename)
  1689.         return 1
  1690.     end
  1691.     if (@reftable is not null and @refid is null) begin
  1692.         RAISERROR (15001, -1, -1, @reftable)
  1693.         return 1
  1694.     end
  1695.  
  1696.     create table #sprefs (
  1697.         id int,                 /* id of reftable */
  1698.         constid int null,         /* id of key */
  1699.         referenced bit            /* well, is it? */
  1700.     )
  1701.  
  1702.     declare @dotables bit, @doall bit, @doprimary bit
  1703.     select     @dotables = case when (@type like 'allt%' or @type like 'actualt%') then 1 else 0 end,
  1704.             @doall = case when (@type like 'all%') then 1 else 0 end,
  1705.             @doprimary = case when (@direction like 'p%') then 1 else 0 end
  1706.  
  1707.     if (@dotables = 1) begin
  1708.         if (@doprimary = 1) begin
  1709.             /* Get all candidate tables (those with Primary/Unique keys in sysconstraints). */
  1710.             insert #sprefs
  1711.                 select distinct id, null, 0 from sysconstraints where status & 0x0f in (1, 2)
  1712.  
  1713.             /* Update the referenced bit if this table references it. */
  1714.             update #sprefs set referenced = 1
  1715.                 where id in (select rkeyid from sysreferences where fkeyid = @id)
  1716.         end else begin
  1717.             /* All user tables are foreign-key candidate tables. */
  1718.             insert #sprefs
  1719.                 select distinct id, null, 0 from sysobjects where sysstat & 0x0f = 3 
  1720.  
  1721.             /* Update the referenced bit if it references this table. */
  1722.             update #sprefs set referenced = 1
  1723.                 where id in (select fkeyid from sysreferences where rkeyid = @id)
  1724.         end    /* direction */
  1725.  
  1726.     end else begin    /* keys */
  1727.         if (@doprimary = 1) begin
  1728.             /* Get all candidate tables (those with Primary/Unique keys in sysconstraints) and the keys. */
  1729.             insert #sprefs
  1730.                 select distinct id, constid, 0 from sysconstraints where status & 0x0f in (1, 2)
  1731.  
  1732.             /* Follow r.rkeyindid back to sysindexes to get the name and then 'rconstid' to see if this table references it. */
  1733.             update #sprefs set referenced = 1 from #sprefs s, sysreferences r, sysindexes i
  1734.                 where r.fkeyid = @id
  1735.                 and i.id = r.rkeyid and i.indid = r.rkeyindid and i.status & 0x1800 <> 0
  1736.                 and s.constid = object_id(i.name)
  1737.  
  1738.         end else begin
  1739.             /* First add tables with FOREIGN keys defined. */
  1740.             insert #sprefs
  1741.                 select distinct id, constid, 0 from sysconstraints where status & 0x0f in (3)
  1742.  
  1743.             /* All user tables are foreign-key candidate tables, so add any tables we haven't yet, if @doall. */
  1744.             /* (This would be used for 'push' key definition; defining FK's from the standpoint of the PK table). */
  1745.             insert #sprefs
  1746.                 select distinct id, null, 0 from sysobjects where sysstat & 0x0f = 3 
  1747.                     and @doall = 1 and id not in (select id from #sprefs)
  1748.  
  1749.             /* Update the referenced bit if it references this table. */
  1750.             update #sprefs set referenced = 1
  1751.                 where constid in (select constid from sysreferences where rkeyid = @id)
  1752.         end    /* direction */
  1753.     end    /* tables or keys */
  1754.     
  1755.     /* Exclude system and MS-internal objects, or tables/keys that aren't in the @reftable we want, if any specified. */
  1756.     delete #sprefs where id in (select id from sysobjects where sysstat & 0x0f <> 3 or category & 0x0002 <> 0)
  1757.             or (@refid is not null and id != @refid)
  1758.  
  1759.     /* Output */
  1760.     if (@tablename is not null)
  1761.         select candidate_table = user_name(o.uid) + '.' + object_name(o.id), 
  1762.             candidate_key = case @dotables when 1 then 'N/A' else object_name(s.constid) end, s.referenced
  1763.             from #sprefs s, sysobjects o where o.id = s.id and (@doall = 1 or s.referenced = 1)
  1764.             order by object_name(o.id), user_name(o.uid), object_name(s.constid)
  1765.     else
  1766.         select candidate_table = user_name(o.uid) + '.' + object_name(o.id), 
  1767.             candidate_key = case @dotables when 1 then 'N/A' else object_name(s.constid) end
  1768.             from #sprefs s, sysobjects o where o.id = s.id
  1769.             order by object_name(o.id), user_name(o.uid), object_name(s.constid)
  1770. go
  1771. /* End sp_MStablerefs */
  1772.  
  1773. /*-- Another SQL60-only proc ---------------------------------------------------*/
  1774. print ''
  1775. print 'Creating sp_MSsettopology'
  1776. print ''
  1777. go
  1778.  
  1779. /* Need this because it will set sysservers columns. */
  1780. sp_configure 'allow updates', 1
  1781. go
  1782. reconfigure with override
  1783. go
  1784.  
  1785. create procedure sp_MSsettopology
  1786.     @server varchar(30), @X int, @Y int
  1787. as
  1788.     update master..sysservers set topologyx = @X, topologyy = @Y
  1789.         where srvname = @server
  1790.     if (@@rowcount = 0) begin
  1791.         RAISERROR (15015, -1, -1, @server)
  1792.         return 1
  1793.     end
  1794.     return 0
  1795. go
  1796. /* End sp_MSsettopology */
  1797.  
  1798. sp_configure 'allow updates', 0
  1799. go
  1800. reconfigure with override
  1801. go
  1802.  
  1803. /*-- Another SQL60-only proc ---------------------------------------------------*/
  1804. print ''
  1805. print 'Creating sp_MSfilterclause'
  1806. print ''
  1807. go
  1808.  
  1809. create procedure sp_MSfilterclause
  1810.     @publication varchar(30), @article varchar(30)
  1811. as
  1812.     /* Return a text column as multiple readtexts of maxcol length */
  1813.     declare @pubid int, @artid int
  1814.     select @pubid = pubid from syspublications where name = @publication
  1815.     if (@pubid is null) begin
  1816.         RAISERROR (15001, 11, -1, @publication)
  1817.         return 1
  1818.     end
  1819.     select @artid = artid from sysarticles where name = @article and pubid = @pubid
  1820.     if (@artid is null) begin
  1821.         RAISERROR (15001, 11, -1, @article)
  1822.         return 1
  1823.     end
  1824.  
  1825.     declare @val varbinary(16), @len int, @ii int, @chunk int
  1826.     select @val = textptr(filter_clause), @len = datalength(filter_clause) from sysarticles where artid = @artid and pubid = @pubid
  1827.     select @ii = 0, @chunk = 255
  1828.  
  1829.     /* Get all the rows of an maxcol size */
  1830.     while @len > @chunk begin
  1831.         readtext sysarticles.filter_clause @val @ii @chunk
  1832.         select @ii = @ii + @chunk, @len = @len - @chunk
  1833.     end
  1834.  
  1835.     /* Get the last chunk */
  1836.     if (@len > 0)
  1837.         readtext sysarticles.filter_clause @val @ii @len
  1838.     return 0
  1839. go
  1840. /* End sp_MSfilterclause */
  1841.  
  1842. /*-- Another SQL60-only proc ---------------------------------------------------*/
  1843. print ''
  1844. print 'Creating sp_MSmatchkey'
  1845. print ''
  1846. go
  1847.  
  1848. create proc sp_MSmatchkey
  1849.     @tablename varchar(92),
  1850.     @col1 varchar(30),
  1851.     @col2 varchar(30) = null,
  1852.     @col3 varchar(30) = null,
  1853.     @col4 varchar(30) = null,
  1854.     @col5 varchar(30) = null,
  1855.     @col6 varchar(30) = null,
  1856.     @col7 varchar(30) = null,
  1857.     @col8 varchar(30) = null,
  1858.     @col9 varchar(30) = null,
  1859.     @col10 varchar(30) = null,
  1860.     @col11 varchar(30) = null,
  1861.     @col12 varchar(30) = null,
  1862.     @col13 varchar(30) = null,
  1863.     @col14 varchar(30) = null,
  1864.     @col15 varchar(30) = null,
  1865.     @col16 varchar(30) = null
  1866. as
  1867.     declare @id int, @ii int, @colnotfound varchar(30), @keycnt int
  1868.     select @id = object_id(@tablename)
  1869.     if (@id is null) begin
  1870.         RAISERROR (15001, -1, -1, @tablename)
  1871.         return 1
  1872.     end
  1873.     select @ii = 1
  1874.     create table #t1 (i int, name varchar (30) null)        /* Join into this... */
  1875.     insert #t1 values (1, @col1)
  1876.     insert #t1 values (2, @col2)
  1877.     insert #t1 values (3, @col3)
  1878.     insert #t1 values (4, @col4)
  1879.     insert #t1 values (5, @col5)
  1880.     insert #t1 values (6, @col6)
  1881.     insert #t1 values (7, @col7)
  1882.     insert #t1 values (8, @col8)
  1883.     insert #t1 values (9, @col9)
  1884.     insert #t1 values (10, @col10)
  1885.     insert #t1 values (11, @col11)
  1886.     insert #t1 values (12, @col12)
  1887.     insert #t1 values (13, @col13)
  1888.     insert #t1 values (14, @col14)
  1889.     insert #t1 values (15, @col15)
  1890.     insert #t1 values (16, @col16)
  1891.     delete #t1 where name is null
  1892.  
  1893.     select @colnotfound = min(name) from #t1 where name not in (select name from syscolumns where id = @id)
  1894.     if (@colnotfound is not null) begin
  1895.         RAISERROR (15253, -1, -1, @colnotfound, @tablename)
  1896.         return 1
  1897.     end
  1898.     select @ii = 1, @keycnt = count(*) from #t1
  1899.  
  1900.     /* Load all indexes which have the matching number of columns into a temp table, then eliminate those which don't qualify. */
  1901.     /* Remember the RID in the nc index is counted as a key */
  1902.     create table #i1 (i int)
  1903.     insert #i1 select indid from sysindexes where status & 0x1800 <> 0
  1904.         and id = @id and keycnt - (case indid when 1 then 0 else 1 end) = @keycnt
  1905.     while (@ii <= @keycnt) begin
  1906.         delete #i1 from #i1 i, #t1 t where t.i = @ii and index_col(@tablename, i.i, t.i) <> t.name
  1907.         select @ii = @ii + 1
  1908.     end
  1909.  
  1910.     /* The qualifying key will be the lowest indid (or the ONLY indid, if we disallow duplicate indexes), if any remain. */
  1911.     select name from sysindexes where id = @id and indid = (select min(i) from #i1)
  1912. go
  1913. /* End sp_MSmatchkey */
  1914.  
  1915. /*-- Another SQL60-only proc ---------------------------------------------------*/
  1916. print ''
  1917. print 'Creating sp_MSsubscriptions'
  1918. print ''
  1919. go
  1920.  
  1921. create procedure sp_MSsubscriptions
  1922.     @subscriber varchar(30) = '%', @dbname varchar(30) = '%', @mode varchar(10) = null
  1923. as
  1924.     if (@subscriber is null)
  1925.         select @subscriber = '%'
  1926.     if (@dbname is null)
  1927.         select @dbname = '%'
  1928.  
  1929.     /* Similar to sp_helpsubscription but intended for SQLOLE's EnumSubscriberSubscriptions, to report on the full */
  1930.     /* server so it needs to return the publication databasename as well, and all subscriptions, not just those active. */
  1931.     IF (@subscriber <> '%' and not exists 
  1932.             (SELECT * FROM sysservers WHERE srvname = @subscriber AND (srvstatus & 0x0004) <> 0)) begin
  1933.         RAISERROR (14010, -1, -1)
  1934.         return 1
  1935.     end
  1936.     IF (@dbname <> '%' and db_id(@dbname) is null) begin
  1937.         RAISERROR (14211, -1, -1, @dbname)
  1938.         return 1
  1939.     end
  1940.     if (@mode = 'drop' and suser_id() <> 1) begin
  1941.         RAISERROR (15003, -1, -1)
  1942.         return 1
  1943.     end
  1944.  
  1945.     create table #t1 (i int identity primary key, cSubscriber varchar(30), cPubDBName varchar(30), cPublication varchar(60), cArticle varchar(60))
  1946.  
  1947.     /* Preprocessor won't replace within quotes so have to use str(). */
  1948.     declare @pubbit varchar(12)
  1949.     select @pubbit = ltrim(str(convert(int, 0x0001)))
  1950.     exec ('declare hC_mssub cursor for select name from master..sysdatabases where category & ' + @pubbit + ' <> 0 and name like ''' + @dbname + '''')
  1951.     open hC_mssub
  1952.     fetch hC_mssub into @dbname
  1953.     while (@@fetch_status >= 0) begin
  1954.         exec ('insert #t1 select ss.srvname, ''' + @dbname + ''', pub.name, art.name from ' +
  1955.                 @dbname + '..syssubscriptions sub, ' +
  1956.                 @dbname + '..syspublications pub, ' +
  1957.                 @dbname + '..sysarticles art, ' +
  1958.                 'master..sysservers ss where ss.srvname like ''' + @subscriber + ''' and sub.srvid = ss.srvid and art.pubid = pub.pubid and sub.artid = art.artid')
  1959.         fetch hC_mssub into @dbname
  1960.     end
  1961.     close hC_mssub
  1962.     deallocate hC_mssub
  1963.  
  1964.     if (@mode = 'drop') begin
  1965.         declare @pubname varchar(60), @artname varchar(60)
  1966.         exec ('declare hC_mssub cursor for select cSubscriber, cPubDBName, cPublication, cArticle from #t1')
  1967.         open hC_mssub
  1968.         fetch hC_mssub into @subscriber, @dbname, @pubname, @artname
  1969.  
  1970.         /* Would be nice to do this in a transaction but schema modifications in transaction aren't supported. */
  1971.         while (@@fetch_status >= 0) begin
  1972.             exec (@dbname + '..sp_dropsubscription ''' + @pubname + ''', ''' + @artname + ''', ''' + @subscriber + '''')
  1973.             fetch hC_mssub into @subscriber, @dbname, @pubname, @artname
  1974.         end
  1975.         close hC_mssub
  1976.         deallocate hC_mssub
  1977.     end else begin
  1978.         select cSubscriber, cPubDBName, cPublication, cArticle from #t1 order by cSubscriber, cPubDBName, cPublication, cArticle
  1979.     end
  1980.     drop table #t1
  1981. go
  1982. /* End sp_MSsubscriptions */
  1983.  
  1984. /*-- Another SQL60-only proc ---------------------------------------------------*/
  1985. print ''
  1986. print 'Creating sp_MSforeach_worker'
  1987. print ''
  1988. go
  1989.  
  1990. /* 
  1991.  * This is the worker proc for all of the "for each" type procs.  Its function is to read the
  1992.  * next replacement name from the cursor (which returns only a single name), plug it into the
  1993.  * replacement locations for the commands, and execute them.  It assumes the cursor "hCForEach"
  1994.  * has already been opened by its caller.
  1995.  */
  1996. create proc sp_MSforeach_worker
  1997.     @command1 varchar(255), @replacechar char(1) = '?', @command2 varchar(255) = null, @command3 varchar(255) = null
  1998. as
  1999.     set nocount on
  2000.     declare @name varchar(100), @namelen int, @q1 varchar(255), @q2 varchar(255), @q3 varchar(255), @q4 varchar(255), @q5 varchar(255)
  2001.     declare @q6 varchar(255), @q7 varchar(255), @q8 varchar(255), @q9 varchar(255), @q10 varchar(255)
  2002.     declare @cmd varchar(255), @replacecharindex int, @useq tinyint, @usecmd tinyint, @nextcmd varchar(255)
  2003.     create table #qtemp(qnum int, qchar varchar(255) null)    /* Temp command storage */
  2004.     open hCForEach
  2005.     fetch hCForEach into @name
  2006.  
  2007.     /* Loop for each database */
  2008.     while (@@fetch_status >= 0) begin
  2009.         /* Initialize. */
  2010.         select @useq = 1, @usecmd = 1, @cmd = @command1, @namelen = datalength(@name)
  2011.         while (@cmd is not null) begin        /* Generate @q* for exec() */
  2012.             /* 
  2013.              * Parse each @commandX into a single executable batch.
  2014.              * Because the expanded form of a @commandX may be > 255, we'll need to allow overflow.
  2015.              * We also may append @commandX's (signified by '++' as first letters of next @command).
  2016.              */
  2017.             select @replacecharindex = charindex(@replacechar, @cmd)
  2018.             while (@replacecharindex <> 0) begin
  2019.                 if (datalength(@cmd) + @namelen - 1 > 255) begin
  2020.                     /* Overflow; put preceding stuff into the temp table */
  2021.                     if (@useq > 9) begin
  2022.                         raiserror 55555 'sp_MSforeach_worker assert failed:  command too long'
  2023.                         close hCForEach
  2024.                         deallocate hCForEach
  2025.                         return 1
  2026.                     end
  2027.                     if (@replacecharindex < @namelen) begin
  2028.                         /* If this happened close to beginning, make sure expansion has enough room. */
  2029.                         /* In this case no trailing space can occur as the row ends with @name. */
  2030.                         select @nextcmd = substring(@cmd, 1, @replacecharindex)
  2031.                         select @cmd = substring(@cmd, @replacecharindex + 1, 255)
  2032.                         select @nextcmd = stuff(@nextcmd, @replacecharindex, 1, @name)
  2033.                         select @replacecharindex = charindex(@replacechar, @cmd)
  2034.                         insert #qtemp values (@useq, @nextcmd)
  2035.                         select @useq = @useq + 1
  2036.                         continue
  2037.                     end
  2038.                     /* Move the string down and stuff() in-place. */
  2039.                     /* Because varchar columns trim trailing spaces, we may need to prepend one to the following string. */
  2040.                     /* In this case, the char to be replaced is moved over by one. */
  2041.                     insert #qtemp values (@useq, substring(@cmd, 1, @replacecharindex - 1))
  2042.                     if (substring(@cmd, @replacecharindex - 1, 1) = ' ') begin
  2043.                         select @cmd = ' ' + substring(@cmd, @replacecharindex, 255)
  2044.                         select @replacecharindex = 2
  2045.                     end else begin
  2046.                         select @cmd = substring(@cmd, @replacecharindex, 255)
  2047.                         select @replacecharindex = 1
  2048.                     end
  2049.                     select @useq = @useq + 1
  2050.                 end
  2051.                 select @cmd = stuff(@cmd, @replacecharindex, 1, @name)
  2052.                 select @replacecharindex = charindex(@replacechar, @cmd)
  2053.             end
  2054.  
  2055.             /* Done replacing for current @cmd.  Get the next one and see if it's to be appended. */
  2056.             select @usecmd = @usecmd + 1
  2057.             select @nextcmd = case (@usecmd) when 2 then @command2 when 3 then @command3 else null end
  2058.             if (@nextcmd is not null and substring(@nextcmd, 1, 2) = '++') begin
  2059.                 insert #qtemp values (@useq, @cmd)
  2060.                 select @cmd = substring(@nextcmd, 3, 255), @useq = @useq + 1
  2061.                 continue
  2062.             end
  2063.  
  2064.             /* Now exec() the generated @q*, and see if we had more commands to exec().  Continue even if errors. */
  2065.             /* Null them first as the no-result-set case won't. */
  2066.             select @q1 = null, @q2 = null, @q3 = null, @q4 = null, @q5 = null, @q6 = null, @q7 = null, @q8 = null, @q9 = null, @q10 = null
  2067.             select @q1 = qchar from #qtemp where qnum = 1
  2068.             select @q2 = qchar from #qtemp where qnum = 2
  2069.             select @q3 = qchar from #qtemp where qnum = 3
  2070.             select @q4 = qchar from #qtemp where qnum = 4
  2071.             select @q5 = qchar from #qtemp where qnum = 5
  2072.             select @q6 = qchar from #qtemp where qnum = 6
  2073.             select @q7 = qchar from #qtemp where qnum = 7
  2074.             select @q8 = qchar from #qtemp where qnum = 8
  2075.             select @q9 = qchar from #qtemp where qnum = 9
  2076.             select @q10 = qchar from #qtemp where qnum = 10
  2077.             truncate table #qtemp
  2078.             exec (@q1 + @q2 + @q3 + @q4 + @q5 + @q6 + @q7 + @q8 + @q9 + @q10 + @cmd)
  2079.             select @cmd = @nextcmd, @useq = 1
  2080.         end /* while @cmd is not null, generating @q* for exec() */
  2081.  
  2082.         /* All commands done for this name.  Go to next one. */
  2083.         fetch hCForEach into @name
  2084.     end /* while FETCH_SUCCESS */
  2085.     close hCForEach
  2086.     deallocate hCForEach
  2087.     return 0
  2088. go
  2089.  
  2090. /* End sp_MSforeach_worker */
  2091.  
  2092. /*-- Another SQL60-only proc ---------------------------------------------------*/
  2093. print ''
  2094. print 'Creating sp_MSforeachdb'
  2095. print ''
  2096. go
  2097.  
  2098. /* 
  2099.  * The following table definition will be created by SQLOLE at start of each connection.
  2100.  * We don't create it here temporarily because we need it in Exec() or upgrade won't work.
  2101.  *
  2102.  *         create table #SQLOLEDbUserProfile (dbid int primary key, profilebits int)
  2103.  */
  2104.  
  2105. create proc sp_MSforeachdb
  2106.     @command1 varchar(255), @replacechar char(1) = '?', @command2 varchar(255) = null, @command3 varchar(255) = null,
  2107.     @precommand varchar(255) = null, @postcommand varchar(255) = null
  2108. as
  2109.     /* This proc returns one or more rows for each accessible db, with each db defaulting to its own result set */
  2110.     /* @precommand and @postcommand may be used to force a single result set via a temp table. */
  2111.  
  2112.     /* Preprocessor won't replace within quotes so have to use str(). */
  2113.     declare @inaccessible varchar(12), @invalidlogin varchar(12)
  2114.     select @inaccessible = ltrim(str(convert(int, 0x03e0)))
  2115.     select @invalidlogin = ltrim(str(convert(int, 0x40000000)))
  2116.  
  2117.     /* If it's a single user db and there's an entry for it in sysprocesses who isn't us, we can't use it. */
  2118.     declare @notsingle varchar(255), @dbstat_singlestr varchar(12)
  2119.     select @dbstat_singlestr = ltrim(str(convert(int, 0x1000)))
  2120.  
  2121.     if (@precommand is not null)
  2122.         exec(@precommand)
  2123.  
  2124.     declare @origdb varchar(30)
  2125.     select @origdb = db_name()
  2126.  
  2127.     /* Create the select */
  2128.     exec('declare hCForEach cursor for select name from master..sysdatabases d, #SQLOLEDbUserProfile p ' +
  2129.             ' where (d.status & ' + @inaccessible + ' = 0) and (d.dbid = p.dbid) and (p.profilebits & ' + @invalidlogin + ' = 0)' + 
  2130.             ' and (d.status & ' + @dbstat_singlestr + ' = 0 or not exists ' + 
  2131.             ' (select * from master..sysprocesses p where dbid = d.dbid and p.spid <> @@spid))' )
  2132.     declare @retval int
  2133.     select @retval = @@error
  2134.     if (@retval = 0)
  2135.         exec @retval = sp_MSforeach_worker @command1, @replacechar, @command2, @command3
  2136.  
  2137.     if (@retval = 0 and @postcommand is not null)
  2138.         exec(@postcommand)
  2139.  
  2140.     exec ('use ' + @origdb)
  2141.     return @retval
  2142. go
  2143. /* End sp_MSforeachdb */
  2144.  
  2145. /*-- Another SQL60-only proc ---------------------------------------------------*/
  2146. print ''
  2147. print 'Creating sp_MSforeachtable'
  2148. print ''
  2149. go
  2150.  
  2151. create proc sp_MSforeachtable
  2152.     @command1 varchar(255), @replacechar char(1) = '?', @command2 varchar(255) = null, @command3 varchar(255) = null, @whereand varchar(255) = null,
  2153.     @precommand varchar(255) = null, @postcommand varchar(255) = null
  2154. as
  2155.     /* This proc returns one or more rows for each table (optionally, matching @where), with each table defaulting to its own result set */
  2156.     /* @precommand and @postcommand may be used to force a single result set via a temp table. */
  2157.  
  2158.     /* Preprocessor won't replace within quotes so have to use str(). */
  2159.     declare @mscat varchar(12), @objtypebits varchar(12), @usertablestat varchar(12)
  2160.     select @mscat = ltrim(str(convert(int, 0x0002)))
  2161.     select @objtypebits = ltrim(str(convert(int, 0x0f)))
  2162.     select @usertablestat = ltrim(str(convert(int, 3)))
  2163.  
  2164.     if (@precommand is not null)
  2165.         exec(@precommand)
  2166.  
  2167.     /* Create the select */
  2168.     exec('declare hCForEach cursor for select user_name(uid) + ''.'' + object_name(id) from sysobjects o '
  2169.             + ' where o.sysstat & ' + @objtypebits + ' = ' + @usertablestat + ' and o.category & ' + @mscat + ' = 0 '
  2170.             + @whereand)
  2171.     declare @retval int
  2172.     select @retval = @@error
  2173.     if (@retval = 0)
  2174.         exec @retval = sp_MSforeach_worker @command1, @replacechar, @command2, @command3
  2175.  
  2176.     if (@retval = 0 and @postcommand is not null)
  2177.         exec(@postcommand)
  2178.  
  2179.     return @retval
  2180. go
  2181. /* End sp_MSforeachtable */
  2182.  
  2183. /*-- Another SQL60-only proc ---------------------------------------------------*/
  2184. print ''
  2185. print 'Creating sp_MSloginmappings'
  2186. print ''
  2187. go
  2188.  
  2189. create proc sp_MSloginmappings
  2190.     @loginname varchar(30) = null
  2191. as
  2192.     /* Gotta be sa to see other than just current login. */
  2193.     declare @numlogins int, @whereloginname varchar(100), @name varchar(30), @retval int
  2194.     if (@loginname is null)
  2195.         select @numlogins = 2
  2196.     else
  2197.         select @numlogins = count(*) from syslogins where name like @loginname
  2198.  
  2199.     if (@numlogins = 0) begin
  2200.         RAISERROR (14220, -1, -1, @loginname)        /* Login not found */
  2201.         return 1
  2202.     end
  2203.     if (suser_id() <> 1 and (@numlogins > 1 or suser_id() <> suser_id(@loginname))) begin
  2204.         RAISERROR (14301, -1, -1, '')                /* Only sa can see other than the current login */
  2205.         return 1
  2206.     end
  2207.     if (@loginname is not null)
  2208.         select @whereloginname = ' where name like ''' + @loginname + ''''
  2209.  
  2210.     /*
  2211.      * This proc returns a result set with one or more rows for each database for which a login is a user or aliased to one.
  2212.      * If loginname is specified, the results are limited to that login.  First load a temp table with all logins that are
  2213.      * in a db, then add those which aren't mapped to any db.
  2214.      */
  2215.     create table #loginmappings(LoginName varchar(30), DBName varchar(30) null, UserName varchar(30) null, AliasName varchar(30) null)
  2216.     exec @retval = sp_MSforeachdb 
  2217.         'use ? INSERT #loginmappings select l.name, db_name(), u.name, null from master..syslogins l, sysusers u where l.suid = u.suid',
  2218.         '?',
  2219.         '++ UNION select l.name, db_name(), null, u.name from master..syslogins l, sysusers u, sysalternates a where l.suid = a.suid and u.suid = a.altsuid'
  2220.     if (@retval <> 0)
  2221.         return 1
  2222.     insert #loginmappings select l.name, null, null, null from master..syslogins l where l.name not in (select LoginName from #loginmappings)
  2223.  
  2224.     /* Now bring them out by loginname, each in its own result set. */
  2225.     exec('declare hCForEachLogin cursor for select name from syslogins ' + @whereloginname + ' order by name')
  2226.     if (@@error = 0)
  2227.         open hCForEachLogin
  2228.     if (@@error <> 0)
  2229.         return @@error
  2230.     fetch hCForEachLogin into @name
  2231.     while (@@fetch_status >= 0) begin
  2232.         select * from #loginmappings where LoginName = @name
  2233.         fetch hCForEachLogin into @name
  2234.     end /* FETCH_SUCCESS */
  2235.  
  2236.     close hCForEachLogin
  2237.     deallocate hCForEachLogin
  2238.     return @@error
  2239. go
  2240. /* End sp_MSloginmappings */
  2241.  
  2242.  
  2243.  
  2244. /*******************************************************************************/
  2245. print ''
  2246. print 'Creating sp_MSuniquename'
  2247. print ''
  2248. go
  2249.  
  2250. create procedure sp_MSuniquename 
  2251.     @seed varchar(30), @start int = null
  2252. as
  2253.     /* Return a unique name for sysobjects, based on a passed-in seed. */
  2254.     set nocount on
  2255.     declare @i int, @append varchar(10), @seedlen int, @temp varchar(30), @recalcseedlen int
  2256.     select @i = 1, @seedlen = datalength(@seed), @recalcseedlen = 1
  2257.     if (@start is not null and @start >= 0)
  2258.         select @i = @start
  2259.     while 1 < 2
  2260.     begin
  2261.         /* This is probably overkill, but start at max length of seed name, leaving room under SYSNAMELEN for @append. */
  2262.         /* We'll work our way back along the string if more room needed (pathological user). */
  2263.         select @append = ltrim(str(@i)) + '__' + ltrim(str(@@spid))
  2264.         if (@recalcseedlen = @i)
  2265.         begin
  2266.             select @recalcseedlen = @recalcseedlen * 10
  2267.             if ((@seedlen + datalength(@append)) > 30)
  2268.                 select @seedlen = 30 - datalength(@append)
  2269.         end
  2270.         select @temp = substring(@seed, 1, @seedlen) + @append        
  2271.  
  2272.         /* If I don't set a limit somewhere, it's gonna look hung -- I'd rather get a nonunique error. */
  2273.         if object_id(@temp) is null or @i > 999999        /* if increased, watch out for overflow of @recalcseedlen */
  2274.         begin
  2275.             set nocount off
  2276.             select Name = @temp, Next = @i + 1
  2277.             return 0
  2278.         end
  2279.         select @i = @i + 1
  2280.     end
  2281. go
  2282. /* End sp_MSuniquename */
  2283.  
  2284. /*******************************************************************************/
  2285. print ''
  2286. print 'Creating sp_MSkilldb'
  2287. print ''
  2288. go
  2289.  
  2290. sp_configure updat, 1
  2291. go
  2292. reconfigure with override
  2293. go
  2294.  
  2295. create proc sp_MSkilldb
  2296.     @dbname varchar(30)
  2297. as
  2298.     
  2299.     if (@@trancount > 0) begin
  2300.         
  2301.         RAISERROR (15002, -1, -1, 'sp_MSkilldb')
  2302.         return 1
  2303.     end
  2304.  
  2305.     if (suser_id() <> 1) begin
  2306.         
  2307.         RAISERROR (15003, -1, -1, '')
  2308.         return 1
  2309.     end
  2310.  
  2311.     /* Set this db to suspect, then let dbcc dbrepair kill it for us. */
  2312.     update master..sysdatabases set status = status | 0x0100
  2313.         where name = @dbname
  2314.     if (@@rowcount = 0) begin
  2315.         
  2316.         RAISERROR (14211, -1, -1, @dbname)
  2317.         return 1
  2318.     end
  2319.     dbcc dbrepair(@dbname, dropdb)
  2320.     return 0
  2321. go
  2322.  
  2323. sp_configure updat, 0
  2324. go
  2325. reconfigure with override
  2326. go
  2327.  
  2328. /* End sp_MSkilldb */
  2329.  
  2330. /*******************************************************************************/
  2331. print ''
  2332. print 'Creating sp_MSdbuserprofile'
  2333. print ''
  2334. go
  2335.  
  2336. create proc sp_MSdbuserprofile
  2337.     @mode varchar(10) = 'init', @qual varchar(30) = '%'
  2338. as
  2339.  
  2340. /* Order of privilege evaluation is:  user granted/revoked, then group granted/revoked, then public granted/revoked */
  2341.  
  2342.  
  2343.  
  2344.  
  2345.  
  2346.  
  2347.  
  2348.     /* If 'srv', we're selecting the server (master db) user profile - currently, just create db priv. */
  2349.     declare @bits int, @gid int, @prot int
  2350.     if (lower(@mode) like 'serv%') begin
  2351.         select @bits = 0x0000
  2352.         if (suser_id() = 1) begin
  2353.             /* sa has everything */
  2354.             select @bits = 0x0007
  2355.         end else begin
  2356.             select @prot = null select @prot = protecttype from sysprotects where action = 203 and uid = user_id()
  2357.             if (@prot is null) select @prot = protecttype from sysprotects where action = 203 and uid = (select gid from sysusers where uid = user_id())
  2358.             if (@prot is null) select @prot = protecttype from sysprotects where action = 203 and uid = user_id('public')
  2359.             if (@prot = 205) select @bits = @bits | 0x0002
  2360.  
  2361.             select @prot = null select @prot = protecttype from sysprotects where action = 224 and uid = user_id() and id = object_id('sp_addextendedproc')
  2362.             if (@prot is null) select @prot = protecttype from sysprotects where action = 224 and uid = (select gid from sysusers where uid = user_id()) and id = object_id('sp_addextendedproc')
  2363.             if (@prot is null) select @prot = protecttype from sysprotects where action = 224 and uid = user_id('public') and id = object_id('sp_addextendedproc')
  2364.             if (@prot = 205) select @bits = @bits | 0x0004
  2365.         end
  2366.         select @bits
  2367.         return 0
  2368.     end
  2369.  
  2370.  
  2371.     /* Just list the current user profile */
  2372.     if (lower(@mode) = 'list') begin
  2373.         exec ('select db_name(dbid), convert(binary(4), profilebits) from #SQLOLEDbUserProfile')
  2374.         return 0
  2375.     end
  2376.  
  2377.     /* If 'init', just load the table. */
  2378.     if (lower(@mode) like 'ini%') begin
  2379.         /* Make sure we're either in master or only doing it to current db. */
  2380.         if (db_id() <> 1)
  2381.             select @qual = db_name()
  2382.  
  2383.         /* First clear out the table.  Do it in an exec() in case we're just selecting from cmdline debugging. */
  2384.         exec ('delete #SQLOLEDbUserProfile from #SQLOLEDbUserProfile p, master..sysdatabases d where d.name like ''' + @qual + ''' and p.dbid = d.dbid')
  2385.  
  2386.         /* See if we're to select after adding. */
  2387.         declare @origmode varchar(10)
  2388.         select @origmode = @mode
  2389.         if (@mode like '%sel%')
  2390.             select @mode = '''addsel'''
  2391.         else
  2392.             select @mode = '''add'''
  2393.  
  2394.         /* Preprocessor won't replace within quotes so have to use str(). */
  2395.         declare @invalidlogin varchar(12)
  2396.         select @invalidlogin = ltrim(str(convert(int, 0x40000000)))
  2397.  
  2398.         /* Select all matching databases -- we want an entry even for inaccessible ones. */
  2399.         declare @dbid smallint, @dbidstr varchar(12), @dbstat smallint, @dbname varchar(30)
  2400.         exec('declare hCdbs cursor for select name, dbid, status from master..sysdatabases where name like ''' + @qual + '''')
  2401.         open hCdbs
  2402.  
  2403.         /* Loop for each database, and if it's accessible, recursively call ourselves to add it. */
  2404.         fetch hCdbs into @dbname, @dbid, @dbstat
  2405.         while (@@fetch_status >= 0) begin
  2406.             /* Preprocessor won't replace within quotes so have to use str(). */
  2407.             select @dbidstr = ltrim(str(convert(int, @dbid)))
  2408.  
  2409.             /* If it's a single user db and there's an entry for it in sysprocesses who isn't us, we can't use it. */
  2410.             declare @single_lockedout int
  2411.             select @single_lockedout = @dbstat & 0x1000
  2412.             if (@single_lockedout <> 0)
  2413.                 select @single_lockedout = 0 where not exists 
  2414.                     (select * from master..sysprocesses p where dbid = @dbid and p.spid <> @@spid)
  2415.  
  2416.             /* First see if the db is accessible (not in load, recovery, offline, single-use with another user besides us, etc.) */
  2417.             if ((@single_lockedout <> 0) or ((@dbstat & 0x03e0) <> 0)) begin
  2418.                 /* Inaccessible, but we can set dbo if we're sa or suser_id() is db owner suid. */
  2419.                 declare @dbbits int, @dbbitstr varchar(12)
  2420.                 select @dbbits = 0x80000000
  2421.                 if (suser_id() = 1 or suser_id() = (select suid from sysdatabases where dbid = @dbid))
  2422.                     select @dbbits = @dbbits | 0x0001
  2423.                 select @dbbitstr = ltrim(convert(varchar(12), @dbbits))
  2424.                 exec ('insert #SQLOLEDbUserProfile values (' + @dbidstr + ', ' + @dbbitstr + ')')
  2425.                 if (lower(@mode) like '%sel%')
  2426.                     select 'profile bitmask' = @dbbits
  2427.             end else begin
  2428.                 exec (@dbname + '..sp_MSdbuserprofile ' + @mode)
  2429.             end
  2430.             
  2431.             /* The exec() may have failed if we are not sa login and have not been added as a user to @dbname. */
  2432.             if (@@error <> 0)
  2433.                 exec ('insert #SQLOLEDbUserProfile values (' + @dbidstr + ', ' + @invalidlogin + ')')
  2434.             fetch hCdbs into @dbname, @dbid, @dbstat
  2435.         end /* while FETCH_SUCCESS */
  2436.         close hCdbs
  2437.         deallocate hCdbs
  2438.  
  2439.         /* Return the list if desired. */
  2440.         if (lower(@origmode) = 'initlist')
  2441.             exec sp_MSdbuserprofile 'list'
  2442.         return 0
  2443.     end
  2444.  
  2445.     /* If 'drop', just do it. */
  2446.     if (@mode = 'drop') begin
  2447.         exec ('delete #SQLOLEDbUserProfile where dbid = db_id()')
  2448.         return 0
  2449.     end
  2450.  
  2451.  
  2452.  
  2453.  
  2454.  
  2455.     /* All other modes require a creation of a profile bitmask. */
  2456.     if (user_id() = 1) begin
  2457.         /* sa/Dbo has everything. */
  2458.         select @bits = 0x00ff
  2459.     end else begin
  2460.         /* Not dbo so get individual privileges */
  2461.         select @bits = 0x0000, @gid = gid from sysusers where uid = user_id()
  2462.         select @prot = null select @prot = protecttype from sysprotects where action = 198 and uid = user_id()
  2463.         if (@prot is null) select @prot = protecttype from sysprotects where action = 198 and uid = (select gid from sysusers where uid = user_id())
  2464.         if (@prot is null) select @prot = protecttype from sysprotects where action = 198 and uid = user_id('public')
  2465.         if (@prot = 205) select @bits = @bits | 0x0002
  2466.  
  2467.         select @prot = null select @prot = protecttype from sysprotects where action = 207 and uid = user_id()
  2468.         if (@prot is null) select @prot = protecttype from sysprotects where action = 207 and uid = (select gid from sysusers where uid = user_id())
  2469.         if (@prot is null) select @prot = protecttype from sysprotects where action = 207 and uid = user_id('public')
  2470.         if (@prot = 205) select @bits = @bits | 0x0004
  2471.  
  2472.         select @prot = null select @prot = protecttype from sysprotects where action = 222 and uid = user_id()
  2473.         if (@prot is null) select @prot = protecttype from sysprotects where action = 222 and uid = (select gid from sysusers where uid = user_id())
  2474.         if (@prot is null) select @prot = protecttype from sysprotects where action = 222 and uid = user_id('public')
  2475.         if (@prot = 205) select @bits = @bits | 0x0008
  2476.  
  2477.         select @prot = null select @prot = protecttype from sysprotects where action = 228 and uid = user_id()
  2478.         if (@prot is null) select @prot = protecttype from sysprotects where action = 228 and uid = (select gid from sysusers where uid = user_id())
  2479.         if (@prot is null) select @prot = protecttype from sysprotects where action = 228 and uid = user_id('public')
  2480.         if (@prot = 205) select @bits = @bits | 0x0010
  2481.  
  2482.         select @prot = null select @prot = protecttype from sysprotects where action = 233 and uid = user_id()
  2483.         if (@prot is null) select @prot = protecttype from sysprotects where action = 233 and uid = (select gid from sysusers where uid = user_id())
  2484.         if (@prot is null) select @prot = protecttype from sysprotects where action = 233 and uid = user_id('public')
  2485.         if (@prot = 205) select @bits = @bits | 0x0020
  2486.  
  2487.         select @prot = null select @prot = protecttype from sysprotects where action = 235 and uid = user_id()
  2488.         if (@prot is null) select @prot = protecttype from sysprotects where action = 235 and uid = (select gid from sysusers where uid = user_id())
  2489.         if (@prot is null) select @prot = protecttype from sysprotects where action = 235 and uid = user_id('public')
  2490.         if (@prot = 205) select @bits = @bits | 0x0040
  2491.  
  2492.         select @prot = null select @prot = protecttype from sysprotects where action = 236 and uid = user_id()
  2493.         if (@prot is null) select @prot = protecttype from sysprotects where action = 236 and uid = (select gid from sysusers where uid = user_id())
  2494.         if (@prot is null) select @prot = protecttype from sysprotects where action = 236 and uid = user_id('public')
  2495.         if (@prot = 205) select @bits = @bits | 0x0080
  2496.     end
  2497.  
  2498.  
  2499.     /* We have the profile bitmask, now see what to do with it. */
  2500.     if (lower(@mode) like 'add%') begin
  2501.         declare @bitstr varchar(12)
  2502.         select @bitstr = ltrim(str(convert(int, @bits)))
  2503.         exec ('insert #SQLOLEDbUserProfile values (db_id(), ' + @bitstr + ')')
  2504.     end
  2505.  
  2506.     if (lower(@mode) like '%sel%') begin
  2507.         if (lower(@qual) like 'bin%')        /* For visual debugging */
  2508.             select 'profile bitmask' = convert(binary(4), @bits)
  2509.         else
  2510.             select 'profile bitmask' = @bits
  2511.     end 
  2512. go
  2513. /* End sp_MSdbuserprofile */
  2514.  
  2515. /*******************************************************************************/
  2516. print ''
  2517. print 'Creating sp_MSobjectprivs'
  2518. print ''
  2519. go
  2520.  
  2521. create proc sp_MSobjectprivs
  2522.     @objname varchar(92) = null, @mode varchar(10) = 'object'    /* or 'user' */
  2523. as
  2524.     set nocount on
  2525.  
  2526.     /* 
  2527.      * To get around a 4.21 subquery bug where returning count(*) of 0 (for proc cols)
  2528.      * causes the result set to return no rows, we need two passes; one to get the
  2529.      * objects, and another to explicitly use a value (@cols) instead of a subquery.
  2530.      */
  2531.     declare @id int, @uid int, @cols int
  2532.     select @id = null, @uid = null
  2533.     if (@mode like 'us%')
  2534.         select @uid = user_id(@objname)
  2535.     else
  2536.         select @id = object_id(@objname)
  2537.     if (@id is null and @uid is null) begin
  2538.         
  2539.         
  2540.         RAISERROR (15001, -1, -1, @objname)
  2541.         return 1
  2542.     end
  2543.  
  2544.     /* Get a temp list of objects we're interested in.  Do not include repl_* users. */
  2545.     create table #objs(
  2546.         id int
  2547.     )
  2548.     insert #objs select distinct p.id from sysprotects p 
  2549.         where (@id is null or p.id = @id)
  2550.         and (@uid is null or p.uid = @uid)
  2551.         and p.action in (193, 195, 196, 197, 224, 26) and p.uid not in (16382, 16383)
  2552.  
  2553.     /* Temp table will hold output for final select */
  2554.     create table #output (
  2555.         action int,
  2556.         colid int null,
  2557.         uid int,
  2558.         protecttype int,
  2559.         id int
  2560.     )
  2561.  
  2562.     /* Use a "fake cursor" by deleting successive id's from #objs, as this must run on 4.21 */
  2563.     select @id = min(id) from #objs
  2564.     while (@id is not null) begin
  2565.         select @cols = count(*) from syscolumns c where c.id = @id
  2566.         insert #output select p.action, a.number, p.uid, p.protecttype, p.id
  2567.             from master.dbo.spt_values a, sysprotects p
  2568.             where convert(tinyint, substring( isnull(p.columns, 0x01), a.low, 1)) & a.high !=0
  2569.             and (p.id = @id)
  2570.             and (@uid is null or p.uid = @uid)
  2571.             and a.number <= @cols
  2572.             and a.type = 'P'
  2573.         /* Increment our "fake cursor" column and get the next one. */
  2574.         delete #objs where id = @id
  2575.         select @id = min(id) from #objs
  2576.     end
  2577.  
  2578.     /*
  2579.      * Organize so that the non-collist privileges are returned first.. this allows
  2580.      * scripting to combine them.  sysprotects.action is tinyint, so the hibyte won't conflict.
  2581.      */
  2582.  
  2583.     update #output set action = action | 0x10000000 where colid <> 0
  2584.  
  2585.     /*
  2586.      * Order output by uid so Public will script before other groups (we need to script privs for public before
  2587.      * other groups, before users; otherwise sysprotects doesn't hold onto things right).  Sub-order is by object id
  2588.      * so we know when we're done with one object and onto the next, then by protecttype to group all GRANTs and
  2589.      * REVOKEs together, and lastly by action (including ORDER_ACTION_BIT so scripting can be more efficient)
  2590.      * because we may have multiple rows for columns.
  2591.      */
  2592.     set nocount off
  2593.     select p.action & ~convert(int, 0x10000000), 'column' = col_name(p.id, p.colid), p.uid, 'username' = user_name(p.uid), 
  2594.             p.protecttype, o.name, 'owner' = user_name(o.uid), p.id 
  2595.         from #output p, sysobjects o 
  2596.         where o.id = p.id 
  2597.         order by p.uid, p.id, p.protecttype, p.action
  2598. go
  2599. /* End sp_MSobjectprivs */
  2600.  
  2601. /*******************************************************************************/
  2602. /* Need to create the version proc here so we can set its category bit */
  2603. go
  2604. create procedure sp_MSSQLOLE_version
  2605. as
  2606.     /* Values for this are same as @@microsoft_version:  0xrraaiibb (reserved, major, minor, build). */
  2607.     declare @i int
  2608.     select @i = 0x00063201    /* Must be in hex! */
  2609.     /* Select the numeric value, and a conversion to make it readable */
  2610.     select 'Microsoft SQLOLE Scripts' = @i, 'Version' = convert(binary(4), @i)
  2611. go
  2612.  
  2613. /********************* Grant privileges *********************************/
  2614. print ''
  2615. print 'Granting execute permissions on procedures'
  2616.  
  2617. grant execute on sp_MShelpcolumns to public
  2618. grant execute on sp_MShelpindex to public
  2619. grant execute on sp_MShelptype to public
  2620. grant execute on sp_MSdependencies to public
  2621. grant execute on sp_MStablespace to public
  2622. grant execute on sp_MSindexspace to public
  2623. grant execute on sp_MSuniquename to public
  2624. grant execute on sp_MSkilldb to public
  2625. grant execute on sp_MSdbuserprofile to public
  2626. grant execute on sp_MSobjectprivs to public
  2627.  
  2628. grant execute on sp_MSgetalertinfo to public
  2629. grant execute on sp_MSsetalertinfo to public
  2630. grant execute on sp_MSgetexecinfo to public
  2631. grant execute on sp_MSsetexecinfo to public
  2632. grant execute on sp_MStablekeys to public
  2633. grant execute on sp_MStablechecks to public
  2634. grant execute on sp_MStablerefs to public
  2635. grant execute on sp_MSsettopology to public
  2636. grant execute on sp_MSfilterclause to public
  2637. grant execute on sp_MSmatchkey to public
  2638. grant execute on sp_MSsubscriptions to public
  2639. grant execute on sp_MSforeachdb to public
  2640. grant execute on sp_MSforeachtable to public
  2641. grant execute on sp_MSloginmappings to public
  2642. grant execute on sp_MSforeach_worker to public
  2643.  
  2644.  
  2645.  
  2646. grant execute on sp_MSSQLOLE_version to public
  2647. go
  2648.  
  2649. /********************** Verify object creation and update category bit for objects *********************************/
  2650.  
  2651. /***************************************************
  2652.  ******************* SQL60 *************************
  2653.  ***************************************************
  2654.  */
  2655.  
  2656. exec sp_configure 'allow updates',0
  2657. go
  2658. reconfigure with override
  2659. go
  2660.  
  2661. print ''
  2662. print 'Checking objects created by sqlole60.sql.'
  2663. go
  2664.  
  2665. /* This kills the conn with a sev-20 raiserror on failure. */
  2666. exec sp_check_objects 'sqlole'
  2667. go
  2668.  
  2669. exec sp_configure 'allow updates', 0
  2670. go
  2671. reconfigure with override
  2672. go
  2673.  
  2674.  
  2675.  
  2676.  
  2677.  
  2678.  
  2679.  
  2680.  
  2681.  
  2682.  
  2683.  
  2684.  
  2685.  
  2686.  
  2687.  
  2688.  
  2689.  
  2690.  
  2691.  
  2692.  
  2693.  
  2694.  
  2695.  
  2696.  
  2697.  
  2698.  
  2699.  
  2700.  
  2701.  
  2702.  
  2703.  
  2704.  
  2705.  
  2706.  
  2707.  
  2708.  
  2709.  
  2710.  
  2711.  
  2712.  
  2713.  
  2714.  
  2715.  
  2716.  
  2717.  
  2718.  
  2719.  
  2720.  
  2721.  
  2722.  
  2723.  
  2724.  
  2725.  
  2726.  
  2727.  
  2728.  
  2729.  
  2730.  
  2731.  
  2732.  
  2733.  
  2734.  
  2735.  
  2736.  
  2737.  
  2738.  
  2739.  
  2740.  
  2741.  
  2742.  
  2743.  
  2744.  
  2745.  
  2746.  
  2747.  
  2748.  
  2749.  
  2750.  
  2751.  
  2752.  
  2753.  
  2754.  
  2755.  
  2756.  
  2757.  
  2758.  
  2759.  
  2760.  
  2761.  
  2762.  
  2763.  
  2764.  
  2765.  
  2766.  
  2767.  
  2768.  
  2769.  
  2770.  
  2771.  
  2772.  
  2773.  
  2774.  
  2775.  
  2776.  
  2777.  
  2778.  
  2779.  
  2780.  
  2781.  
  2782.  
  2783.  
  2784.  
  2785.  
  2786.  
  2787.  
  2788.  
  2789.  
  2790.  
  2791.  
  2792.  
  2793.  
  2794.  
  2795.  
  2796.  
  2797.  
  2798.  
  2799.  
  2800.  
  2801.  
  2802.  
  2803.  
  2804.  
  2805.  
  2806.  
  2807.  
  2808.  
  2809.  
  2810.  
  2811.  
  2812.  
  2813.  
  2814.  
  2815.  
  2816.  
  2817.  
  2818.  
  2819.  
  2820.  
  2821.  
  2822.  
  2823.  
  2824.  
  2825.  
  2826.  
  2827.  
  2828.  
  2829.  
  2830.  
  2831.  
  2832.  
  2833.  
  2834.  
  2835.  
  2836.  
  2837.  
  2838.  
  2839.  
  2840.  
  2841.  
  2842.  
  2843.  
  2844. if (object_id('sp_MSSQLOLE_version') is not null) begin
  2845.     print ''
  2846.     print ''
  2847.     print ' Successful installation.'
  2848.     exec sp_MSSQLOLE_version
  2849. end
  2850.  
  2851. /************* DUMP THE TRANSACTION LOG **************************************/
  2852. /* Comment this out if you don't want your log dumped.  If you rerun this    */
  2853. /* script periodically, you will run out of transaction log space.           */
  2854. print ''
  2855. print 'Dumping transaction log...'
  2856. print ''
  2857. go
  2858. dump tran master with no_log
  2859. go
  2860. checkpoint
  2861. go
  2862. /************* END DUMP THE TRANSACTION LOG **********************************/
  2863.  
  2864.