home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World Interactive 1996 October / pcwoct96.zip / pcwoct96 / INSTALL / ODBC / INSTCAT.SQL < prev    next >
Text File  |  1995-01-13  |  91KB  |  3,114 lines

  1. /*
  2. **    INSTCAT.SQL
  3. **    Installs catalog stored procedures on the Microsoft SQL Server.
  4. **    Copyright 1994, Microsoft Corp.  All rights reserved.
  5. */
  6.  
  7. /*
  8. NOTE:  you MUST change the last row inserted into spt_server_info
  9. to be version number of this file.    the convention is jj.nn.dddd, where
  10. jj is the major version number ("01" now), nn is the minor version number
  11. ("01" now), and dddd is the date in the form of month and day (mmdd) of
  12. the date you check in this file.  Add (year-1991)*12 to the month to keep
  13. in sync with the driver version numbers, i.e. checking in on Feb 5 1993
  14. would mean setting the value to 01.01.2605.
  15. */
  16.  
  17. /****************************************************************************/
  18. /* This portion sets up the ability to perform all the functions in this    */
  19. /* script                                                                    */
  20. /****************************************************************************/
  21. use master
  22. go
  23. dump tran master with truncate_only
  24. go
  25.  
  26. if exists (select * from sysobjects
  27.        where name = 'sp_configure' and sysstat & 7 = 4)
  28. begin
  29.     execute sp_configure 'update',1
  30. end
  31. reconfigure with override
  32. go
  33.  
  34. /*
  35. ** If old versions of tables exist, drop them.
  36. */
  37. if (exists (select * from sysobjects
  38.         where name = 'MSdatatype_info' and sysstat & 7 = 3))
  39.     drop table MSdatatype_info
  40. go
  41. if (exists (select * from sysobjects
  42.         where name = 'MSdatatype_info_ext' and sysstat & 7 = 3))
  43.     drop table MSdatatype_info_ext
  44. go
  45. if (exists (select * from sysobjects
  46.         where name = 'MStable_types' and sysstat & 7 = 3))
  47.     drop table MStable_types
  48. go
  49. if (exists (select * from sysobjects
  50.         where name = 'MSserver_info' and sysstat & 7 = 3))
  51.     drop table MSserver_info
  52. go
  53. if (exists (select * from sysobjects
  54.         where name = 'spt_table_types' and sysstat & 7 = 3))
  55.     drop table spt_table_types    /* no longer used */
  56. go
  57.  
  58. /*
  59. ** If tables or procs already exist, drop them.
  60. */
  61.  
  62. if (exists (select * from sysobjects
  63.         where name = 'spt_datatype_info' and sysstat & 7 = 3))
  64.     drop table spt_datatype_info
  65. go
  66. if (exists (select * from sysobjects
  67.         where name = 'spt_datatype_info_ext' and sysstat & 7 = 3))
  68.     drop table spt_datatype_info_ext
  69. go
  70. if (exists (select * from sysobjects
  71.         where name = 'spt_server_info' and sysstat & 7 = 3))
  72.     drop table spt_server_info
  73. go
  74. if (exists (select * from sysobjects
  75.         where name = 'sp_tables' and sysstat & 7 = 4))
  76.     drop proc sp_tables
  77. go
  78. if (exists (select * from sysobjects
  79.         where name = 'sp_statistics' and sysstat & 7 = 4))
  80.     drop proc sp_statistics
  81. go
  82. if (exists (select * from sysobjects
  83.         where name = 'sp_columns' and sysstat & 7 = 4))
  84.     drop proc sp_columns
  85. go
  86. if (exists (select * from sysobjects
  87.         where name = 'sp_fkeys' and sysstat & 7 = 4))
  88.     drop proc sp_fkeys
  89. go
  90. if (exists (select * from sysobjects
  91.         where name = 'sp_pkeys' and sysstat & 7 = 4))
  92.     drop proc sp_pkeys
  93. dump tran master with truncate_only
  94. go
  95.  
  96. go
  97. if (exists (select * from sysobjects
  98.         where name = 'sp_stored_procedures' and sysstat & 7 = 4))
  99.     drop proc sp_stored_procedures
  100. go
  101. if (exists (select * from sysobjects
  102.         where name = 'sp_sproc_columns' and sysstat & 7 = 4))
  103.     drop proc sp_sproc_columns
  104. go
  105. if (exists (select * from sysobjects
  106.         where name = 'sp_table_privileges' and sysstat & 7 = 4))
  107.     drop proc sp_table_privileges
  108. go
  109. if (exists (select * from sysobjects
  110.         where name = 'sp_column_privileges' and sysstat & 7 = 4))
  111.     drop proc sp_column_privileges
  112. go
  113. if (exists (select * from sysobjects
  114.         where name = 'sp_server_info' and sysstat & 7 = 4))
  115.     drop proc sp_server_info
  116. go
  117. if (exists (select * from sysobjects
  118.         where name = 'sp_datatype_info' and sysstat & 7 = 4))
  119.     drop proc sp_datatype_info
  120. go
  121. if (exists (select * from sysobjects
  122.         where name = 'sp_special_columns' and sysstat & 7 = 4))
  123.     drop proc sp_special_columns
  124. go
  125. if (exists (select * from sysobjects
  126.         where name = 'sp_databases' and sysstat & 7 = 4))
  127.     drop proc sp_databases
  128. go
  129.  
  130. dump tran master with truncate_only
  131. go
  132.  
  133. print "creating table spt_datatype_info_ext"
  134. go
  135. create table spt_datatype_info_ext (
  136.                 user_type        smallint    not null,
  137.                 create_params    varchar(32) null)
  138. go
  139.  
  140. grant select on spt_datatype_info_ext to public
  141. go
  142.  
  143.  
  144. insert into spt_datatype_info_ext
  145.     /* CHAR      user_type, create_params */
  146.     values             (1,    "length" )
  147.  
  148. insert into spt_datatype_info_ext
  149.     /* VARCHAR     user_type, create_params */
  150.     values             (2,    "max length" )
  151.  
  152. insert into spt_datatype_info_ext
  153.     /* BINARY     user_type, create_params */
  154.     values             (3,    "length" )
  155.  
  156. insert into spt_datatype_info_ext
  157.     /* VARBINARY user_type, create_params */
  158.     values             (4,    "max length" )
  159.  
  160. insert into spt_datatype_info_ext
  161.     /* SYSNAME     user_type, create_params */
  162.     values             (18,    "max length" )
  163. go
  164.  
  165. print "creating table spt_datatype_info"
  166. go
  167. create table spt_datatype_info (
  168.                 ss_dtype           tinyint        not null,
  169.                 type_name          varchar(32)  not null,
  170.                 data_type          smallint     not null,
  171.                 data_precision     int          null,
  172.                 numeric_scale      smallint     null,
  173.                 numeric_radix      smallint     null,
  174.                 length             int          null,
  175.                 literal_prefix     varchar(32)  null,
  176.                 literal_suffix     varchar(32)  null,
  177.                 create_params      varchar(32)  null,
  178.                 nullable           smallint     not null,
  179.                 case_sensitive     smallint     not null,
  180.                 searchable         smallint     not null,
  181.                 unsigned_attribute smallint     null,
  182.                 money              smallint     not null,
  183.                 auto_increment     smallint     null,
  184.                 local_type_name    varchar(128) not null,
  185.                 aux                int          null)
  186. go
  187.  
  188. /*
  189.     There is a complicated set of SQL used to deal with
  190.     the SQL Server Null data types (MONEYn, INTn, etc.)
  191.     ISNULL is the only conditional SQL Server function that can be used
  192.     to differentiate between these types depending on size.
  193.  
  194.     The aux column in the above table is used to differentiate
  195.     the null data types from the non-null types.
  196.  
  197.     The aux column contains NULL for the null data types and 0
  198.     for the non-null data types.
  199.  
  200.     The following SQL returns the contents of the aux column (0)
  201.     for the non-null data types and returns a variable non-zero
  202.     value for the null data types.
  203.  
  204.                                  " I   I I FFMMDD"
  205.                                  " 1   2 4 484848"
  206.     isnull(d.aux,ascii(substring("666AAA@@@CB??GG",
  207.     2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)
  208.  
  209.     The '2*(d.ss_dtype%35+1)+2-8/c.length' selects a specific character of
  210.     the substring mask depending on the null data type and its size, i.e.
  211.     null MONEY4 or null MONEY8.  The character selected is then converted
  212.     to its binary value and an appropriate bias (i.e. 60) is subtracted to
  213.     return the correct non-zero value.    This value may be used as a
  214.     constant, i.e. ODBC data type, precision, scale, etc., or used as an
  215.     index with a substring to pick out a character string, i.e. type name.
  216.  
  217.     The comments above the substring mask denote which character is
  218.     selected for each null data type, i.e. In (INTn), Fn (FLOATn),
  219.     Mn (MONEYn) and Dn (DATETIMn).
  220. */
  221.  
  222. grant select on spt_datatype_info to public
  223. go
  224.  
  225. /* Get case sensitivity */
  226. if 'A' = 'A' /* create dummy begin block */
  227. begin
  228.     declare @case smallint
  229.  
  230.     select @case = 0
  231.     select @case = 1 where 'a' != 'A'
  232.  
  233.     /* Local Binary */
  234.     insert into spt_datatype_info
  235.     /* ss_type,name    ,data_type,prec,scale,rdx ,len ,prf ,suf ,cp      ,nul,case,srch,unsigned,money,auto,local   ,aux */ values
  236.     (  45     ,"binary",-2       ,null,null ,null,null,"0x",null,"length",1  ,0   ,2   ,null    ,0    ,null,"binary",0)
  237.  
  238.     /* Local Bit */
  239.     insert into spt_datatype_info
  240.     /* ss_type,name ,data_type, prec,scale,rdx,len ,prf ,suf ,cp  ,nul,case,srch,unsigned,money,auto,local,aux */ values
  241.     (  50     ,"bit",-7       ,    1   ,0    ,2  ,null,null,null,null,0  ,0   ,2   ,null    ,0    ,null,"bit",0)
  242.  
  243.     /* Local Char */
  244.     insert into spt_datatype_info
  245.     /* ss_type,name  ,data_type,prec,scale,rdx ,len ,prf,suf,cp      ,nul,case ,srch,unsigned,money,auto,local ,aux */ values
  246.     (  47     ,"char",1        ,null,null ,null,null,"'","'","length",1  ,@case,3   ,null    ,0    ,null,"char",0)
  247.  
  248.     /* Local Datetime */
  249.     insert into spt_datatype_info
  250.     /* ss_type,name      ,data_type,prec,scale,rdx,len,prf,suf,cp  ,nul,case,srch,unsigned,money,auto,local     ,aux */ values
  251.     (  61     ,"datetime",11       ,23  ,3    ,10 ,16 ,"'","'",null,1  ,0   ,3   ,null    ,0    ,null,"datetime",0)
  252.  
  253.     /* Local Smalldatetime */
  254.     insert into spt_datatype_info
  255.     /* ss_type,name           ,data_type,prec,scale,rdx,len,prf,suf,cp  ,nul,case,srch,unsigned,money,auto,local          ,aux */ values
  256.     (  58     ,"smalldatetime",11       ,16  ,0    ,10 ,16 ,"'","'",null,1  ,0   ,3   ,null    ,0    ,null,"smalldatetime",0)
  257.  
  258.     /* Local Datetimn */
  259.     insert into spt_datatype_info  /* sql server type is "datetimn" */
  260.     /* ss_type,name           ,data_type,prec,scale,rdx,len,prf,suf,cp  ,nul,case,srch,unsigned,money,auto,local     ,aux */ values
  261.     (  111    ,"smalldatetime",0        ,0   ,0    ,10 ,0  ,"'","'",null,1  ,0   ,3   ,null    ,0    ,null,"datetime",null)
  262.  
  263.     /* Local Float */
  264.     insert into spt_datatype_info
  265.     /* ss_type,name   ,data_type,prec,scale,rdx,len ,prf ,suf ,cp  ,nul,case,srch,unsigned,money,auto,local  ,aux */ values
  266.     (  62     ,"float",6        ,15  ,null ,10 ,null,null,null,null,1  ,0   ,2   ,0       ,0    ,0   ,"float",0)
  267.  
  268.     /* Local RealFloat */
  269.     insert into spt_datatype_info  /* sql server type is "floatn" */
  270.     /* ss_type,name               ,data_type,prec,scale,rdx,len,prf ,suf ,cp  ,nul,case,srch,unsigned,money,auto,local            ,aux */ values
  271.     (  109    ,"float        real",0        ,0   ,null ,10 ,0  ,null,null,null,1  ,0   ,2   ,0       ,0    ,0   ,"real      float",null)
  272.  
  273.     /* Local Real */
  274.     insert into spt_datatype_info
  275.     /* ss_type,name  ,data_type,prec,scale,rdx,len ,prf ,suf ,cp  ,nul,case,srch,unsigned,money,auto,local ,aux */ values
  276.     (  59     ,"real",7        ,7   ,null ,10 ,null,null,null,null,1  ,0   ,2   ,0       ,0    ,0   ,"real",0)
  277.  
  278.     /* Local Smallmoney */
  279.     insert into spt_datatype_info
  280.     /* ss_type,name        ,data_type,prec,scale,rdx,len ,prf,suf ,cp  ,nul,case,srch,unsigned,money,auto,local       ,aux */ values
  281.     (  122    ,"smallmoney",3        ,10  ,4    ,10 ,null,"$",null,null,1  ,0   ,2   ,0       ,1    ,0   ,"smallmoney",0)
  282.  
  283.     /* Local Int */
  284.     insert into spt_datatype_info
  285.     /* ss_type,name ,data_type,prec,scale,rdx,len ,prf ,suf ,cp  ,nul,case,srch,unsigned,money,auto,local,aux */ values
  286.     (  56     ,"int",4        ,10  ,0    ,10 ,null,null,null,null,1  ,0   ,2   ,0       ,0    ,0   ,"int",0)
  287.  
  288.     /* Local Intn */
  289.     insert into spt_datatype_info  /* sql server type is "intn" */
  290.     /* ss_type,name                  ,data_type,prec,scale,rdx,len,prf ,suf ,cp  ,nul,case,srch,unsigned,money,auto,local               ,aux */ values
  291.     (       38,"smallint     tinyint",0        ,0   ,0    ,10 ,0  ,null,null,null,1  ,0   ,2   ,0       ,0    ,0   ,"tinyint   smallint",null)
  292.  
  293.     /* Local Money */
  294.     insert into spt_datatype_info
  295.     /* ss_type,name   ,data_type,prec,scale,rdx,len ,prf,suf ,cp  ,nul,case,srch,unsigned,money,auto,local  ,aux */ values
  296.     (  60     ,"money",3        ,19  ,4    ,10 ,null,"$",null,null,1  ,0   ,2   ,0       ,1    ,0   ,"money",0)
  297.  
  298.     /* Local Moneyn */
  299.     insert into spt_datatype_info    /* sql server type is "moneyn" */
  300.     /* ss_type,name        ,data_type,prec,scale,rdx,len,prf,suf ,cp  ,nul,case,srch,unsigned,money,auto,local            ,aux */ values
  301.     (  110    ,"smallmoney",0        ,0   ,4    ,10 ,0  ,"$",null,null,1  ,0   ,2   ,0       ,1    ,0   ,"smallmoneymoney",null)
  302.  
  303.     /* Local Smallint */
  304.     insert into spt_datatype_info
  305.     /* ss_type,name      ,data_type,prec,scale,rdx,len ,prf ,suf ,cp  ,nul,case,srch,unsigned,money,auto,local     ,aux */ values
  306.     (  52     ,"smallint",5        ,5   ,0    ,10 ,null,null,null,null,1  ,0   ,2   ,0       ,0    ,0   ,"smallint",0)
  307.  
  308.     /* Local Text */
  309.     insert into spt_datatype_info
  310.     /* ss_type,name  ,data_type,prec      ,scale,rdx ,len       ,prf,suf,cp  ,nul,case ,srch,unsigned,money,auto,local ,aux */ values
  311.     (  35     ,"text",-1       ,2147483647,null ,null,2147483647,"'","'",null,1  ,@case,1   ,null    ,0    ,null,"text",0)
  312.  
  313.     /* Local Varbinary */
  314.     insert into spt_datatype_info
  315.     /* ss_type,name       ,data_type,prec,scale,rdx ,len ,prf ,suf ,cp          ,nul,case,srch,unsigned,money,auto,local      ,aux */ values
  316.     (  37     ,"varbinary",-3       ,null,null ,null,null,"0x",null,"max length",1  ,0   ,2   ,null    ,0    ,null,"varbinary",0)
  317.  
  318.     /* Local Tinyint */
  319.     insert into spt_datatype_info
  320.     /* ss_type,name     ,data_type,prec,scale,rdx,len ,prf ,suf ,cp  ,nul,case,srch,unsigned,money,auto,local    ,aux */ values
  321.     (  48     ,"tinyint",-6       ,3   ,0    ,10 ,null,null,null,null,1  ,0   ,2   ,1       ,0    ,0   ,"tinyint",0)
  322.  
  323.     /* Local Varchar */
  324.     insert into spt_datatype_info
  325.     /* ss_type,name     ,data_type,prec,scale,rdx ,len ,prf,suf,cp          ,nul,case ,srch,unsigned,money,auto,local    ,aux */ values
  326.     (  39     ,"varchar",12       ,null,null ,null,null,"'","'","max length",1  ,@case,3   ,null    ,0    ,null,"varchar",0)
  327.  
  328.     /* Local Image */
  329.     insert into spt_datatype_info
  330.     /* ss_type,name   ,data_type,prec      ,scale,rdx ,len       ,prf ,suf ,cp  ,nul,case,srch,unsigned,money,auto,local  ,aux */ values
  331.     (  34     ,"image",-4       ,2147483647,null ,null,2147483647,"0x",null,null,1  ,0   ,1   ,null    ,0    ,null,"image",0)
  332. end
  333. go
  334.  
  335. dump tran master with truncate_only
  336. go
  337.  
  338. print "creating table spt_server_info"
  339. go
  340. create table spt_server_info (
  341.               attribute_id        int,
  342.               attribute_name    varchar(60),
  343.               attribute_value    varchar(255))
  344. go
  345.  
  346. insert into spt_server_info
  347.     values (1,"DBMS_NAME","Microsoft SQL Server")
  348. insert into spt_server_info
  349.     values (2,"DBMS_VER",@@version)
  350. insert into spt_server_info
  351.     values (10,"OWNER_TERM","owner")
  352. insert into spt_server_info
  353.     values (11,"TABLE_TERM","table")
  354. insert into spt_server_info
  355.     values (12,"MAX_OWNER_NAME_LENGTH","30")
  356. insert into spt_server_info
  357.     values (13,"TABLE_LENGTH","30")
  358. insert into spt_server_info
  359.     values (14,"MAX_QUAL_LENGTH","30")
  360. insert into spt_server_info
  361.     values (15,"COLUMN_LENGTH","30")
  362. insert into spt_server_info
  363.     values (16,"IDENTIFIER_CASE","MIXED")
  364. insert into spt_server_info
  365.     values (17,"TX_ISOLATION","2")
  366. go
  367. /*
  368. ** syscharsets doesn't exist on pre rel. 4.2 servers.
  369. */
  370. if not exists (select * from sysobjects where name = 'syscharsets')
  371.  if 'a' = 'A'    /* pre 4.2 case insensitive server */
  372.         insert into spt_server_info values
  373.            (18,"COLLATION_SEQ",
  374.            'charset=cp850 sort_order=caseless_34 charset_num=2 sort_order_num=49')
  375.      else            /* pre 4.2 case sensitive server */
  376.         insert into spt_server_info values
  377.            (18,"COLLATION_SEQ",
  378.             'charset=cp850 sort_order=bin_cp850 charset_num=2 sort_order_num=40')
  379. go
  380.  
  381. /*    Check if Version 1.11 */
  382. if  (charindex('1.11', @@version) != 0)
  383.    begin
  384.     print ""
  385.     print ""
  386.     print "Installing catalog procedures on a 1.x or 4.0 server:"
  387.     print "Ignore the following error messages"
  388.     print ""
  389.     print ""
  390.    end
  391. go
  392.  
  393. /*
  394. ** Use the insert that utilizes syscharsets if it exists.
  395. */
  396. if exists (select * from sysobjects where name = 'syscharsets')
  397.    insert into spt_server_info
  398.       select 18,"COLLATION_SEQ",
  399.          "charset="+t2.name+" sort_order="+t1.name
  400.          +" charset_num="+rtrim(convert(char(4),t1.csid))+
  401.          " sort_order_num="+rtrim(convert(char(4),t1.id))
  402.      from syscharsets t1, syscharsets t2, sysconfigures t3
  403.      where t1.csid=t2.id and t1.id=t3.value and t3.config=123
  404. go
  405.  
  406. insert into spt_server_info
  407.     values (19,"SAVEPOINT_SUPPORT","Y")
  408. insert into spt_server_info
  409.     values (20,"MULTI_RESULT_SETS","Y")
  410. insert into spt_server_info
  411.     values (22,"ACCESSIBLE_TABLES","Y")
  412. insert into spt_server_info
  413.     values (100,"USERID_LENGTH","30")
  414. insert into spt_server_info
  415.     values (101,"QUALIFIER_TERM","database")
  416. insert into spt_server_info
  417.     values (102,"NAMED_TRANSACTIONS","Y")
  418. insert into spt_server_info
  419.     values (103,"SPROC_AS_LANGUAGE","Y")
  420. insert into spt_server_info
  421.     values (104,"ACCESSIBLE_SPROC","Y")
  422. insert into spt_server_info
  423.     values (105,"MAX_INDEX_COLS","16")
  424. insert into spt_server_info
  425.     values (106,"RENAME_TABLE","Y")
  426. insert into spt_server_info
  427.     values (107,"RENAME_COLUMN","Y")
  428. insert into spt_server_info
  429.     values (108,"DROP_COLUMN","N")
  430. insert into spt_server_info
  431.     values (109,"INCREASE_COLUMN_LENGTH","N")
  432. insert into spt_server_info
  433.     values (110,"DDL_IN_TRANSACTION","N")
  434. insert into spt_server_info
  435.     values (111,"DESCENDING_INDEXES","N")
  436. insert into spt_server_info
  437.     values (112,"SP_RENAME","Y")
  438. insert into spt_server_info
  439.     values (113,"REMOTE_SPROC","Y")
  440. insert into spt_server_info
  441.     values (500,"SYS_SPROC_VERSION","02.00.4127")
  442. go
  443.  
  444. grant select on spt_server_info to public
  445. go
  446.  
  447. print "creating sp_tables"
  448. go
  449.  
  450. create procedure sp_tables(
  451.                @table_name        varchar(32)  = null,
  452.                @table_owner     varchar(32)  = null,
  453.                @table_qualifier varchar(32)  = null,
  454.                @table_type        varchar(100) = null)
  455. as
  456.     declare @type1 varchar(3)
  457.     declare @tableindex int
  458.  
  459.  
  460.     /* Special feature #1:    enumerate databases when owner and name
  461.          are blank but qualifier is explicitly '%'.  */
  462.     if @table_qualifier = '%' and
  463.         @table_owner = '' and
  464.         @table_name = ''
  465.     begin    /* If enumerating databases */
  466.         select
  467.             table_qualifier = name,
  468.             table_owner = convert(varchar(32),null),
  469.             table_name = convert(varchar(32),null),
  470.             table_type = convert(varchar(12),null),
  471.             remarks = convert(varchar(254),null)    /* Remarks are NULL */
  472.         from master..sysdatabases
  473.         where name != 'model'    /* eliminate MODEL database */
  474.         order by table_qualifier
  475.     end
  476.  
  477.     /* Special feature #2:    enumerate owners when qualifier and name
  478.          are blank but owner is explicitly '%'.  */
  479.     else if @table_qualifier = '' and
  480.         @table_owner = '%' and
  481.         @table_name = ''
  482.     begin    /* If enumerating owners */
  483.         select distinct
  484.             table_qualifier = convert(varchar(32),null),
  485.             table_owner = user_name(uid),
  486.             table_name = convert(varchar(32),null),
  487.             table_type = convert(varchar(12),null),
  488.             remarks = convert(varchar(254),null)    /* Remarks are NULL */
  489.         from sysobjects
  490.         order by table_owner
  491.     end
  492.  
  493.     /* Special feature #3:    enumerate table types when qualifier, owner and
  494.          name are blank but table type is explicitly '%'.    */
  495.     else if @table_qualifier = '' and
  496.         @table_owner = '' and
  497.         @table_name = '' and
  498.         @table_type = '%'
  499.     begin    /* If enumerating table types */
  500.         select
  501.             table_qualifier = convert(varchar(32),null),
  502.             table_owner = convert(varchar(32),null),
  503.             table_name = convert(varchar(32),null),
  504.             table_type = rtrim(substring('SYSTEM TABLETABLE       VIEW',(colid-1)*12+1,12)),
  505.             remarks = convert(varchar(254),null)    /* Remarks are NULL */
  506.         from sysobjects o, syscolumns c
  507.         where o.id=c.id and o.name='sysusers' and colid<=3
  508.     end
  509.  
  510.     else
  511.     begin /* end of special features -- do normal processing */
  512.         if @table_qualifier is not null
  513.         begin
  514.             if db_name() != @table_qualifier
  515.             begin
  516.                 if @table_qualifier = ''
  517.                 begin  /* If empty qualifier supplied */
  518.                     /* Force an empty result set */
  519.                     select @table_name = ''
  520.                     select @table_owner = ''
  521.                 end
  522.                 else
  523.                 begin    /* If qualifier doesn't match current database */
  524.                     print "Table qualifier must be name of current database"
  525.                     return
  526.                 end
  527.             end
  528.         end
  529.         if @table_type is null
  530.         begin    /* Select all ODBC supported table types */
  531.             select @type1 = 'SUV'
  532.         end
  533.         else
  534.         begin
  535.             /*    TableType is case sensitive if CS server */
  536.             select @type1 = null
  537.             if (charindex("'SYSTEM TABLE'",@table_type) != 0)
  538.                 select @type1 = @type1 + 'S'    /* Add System Tables */
  539.             if (charindex("'TABLE'",@table_type) != 0)
  540.                 select @type1 = @type1 + 'U'    /* Add User Tables */
  541.             if (charindex("'VIEW'",@table_type) != 0)
  542.                 select @type1 = @type1 + 'V'    /* Add Views */
  543.         end
  544.         if @table_name is null
  545.         begin    /*    If table name not supplied, match all */
  546.             select @table_name = '%'
  547.         end
  548.         else
  549.         begin
  550.             if (@table_owner is null) and (charindex('%', @table_name) = 0)
  551.             begin    /* If owner not specified and table is specified */
  552.                 if exists (select * from sysobjects
  553.                     where uid = user_id()
  554.                     and name = @table_name
  555.                     and (type = 'U' or type = 'V' or type = 'S'))
  556.                 begin    /* Override supplied owner w/owner of table */
  557.                     select @table_owner = user_name()
  558.                 end
  559.             end
  560.         end
  561.         if @table_owner is null /* If no owner supplied, force wildcard */
  562.             select @table_owner = '%'
  563.         select
  564.             table_qualifier = db_name(),
  565.             table_owner = user_name(o.uid),
  566.             table_name = o.name,
  567.             table_type = rtrim(
  568.                 substring('SYSTEM TABLE            TABLE       VIEW       ',
  569.                     (ascii(o.type)-83)*12+1,12)),    /* 'S'=0,'U'=2,'V'=3 */
  570.             remarks = convert(varchar(254),null)    /* Remarks are NULL */
  571.         from sysusers u, sysobjects o
  572.         where
  573.             o.name like @table_name
  574.             and user_name(o.uid) like @table_owner
  575.             and charindex(substring(o.type,1,1),@type1)! = 0 /* Only desired types */
  576.             and u.uid = user_id() /* constrain sysusers uid for use in subquery */
  577.             and (
  578.                 suser_id() = 1     /* User is the System Administrator */
  579.                 or o.uid = user_id()     /* User created the object */
  580.                 /* here's the magic... select the highest precedence of permissions in the order (user,group,public)  */
  581.                 or ((select max(((sign(uid)*abs(uid-16383))*2)+(protecttype&1))
  582.                     from sysprotects p
  583.                     /* outer join to correlate with all rows in sysobjects */
  584.                     where p.id =* o.id
  585.                         /* get rows for public,current user,user's group */
  586.                         and (p.uid = 0 or p.uid = user_id() or p.uid =* u.gid)
  587.                         /* check for SELECT,EXECUTE privilege */
  588.                         and (action in (193,224)))&1     /* more magic...normalize GRANT */
  589.                     ) = 1    /* final magic...compare Grants      */
  590.             )
  591.         order by table_type, table_qualifier, table_owner, table_name
  592.     end
  593. go
  594.  
  595. grant execute on sp_tables to public
  596. go
  597.  
  598. dump tran master with truncate_only
  599. go
  600.  
  601. print "creating sp_statistics"
  602. go
  603.  
  604. /*    Check if Version 4.8 or 4.9 */
  605. if  (charindex('4.8', @@version) = 0
  606.     and charindex('4.9', @@version) = 0)
  607. begin
  608.     print ""
  609.     print ""
  610.     print "Warning:"
  611.     print "you are installing the stored procedures "
  612.     print "on SQL Server with version less than 4.8, "
  613.     print "ignore the following error"
  614. end
  615. go
  616.  
  617. /*    This procedure is for 4.8 and 4.9 servers (catalog difference) */
  618. CREATE PROCEDURE sp_statistics (
  619.                  @table_name        varchar(32),
  620.                  @table_owner        varchar(32) = null,
  621.                  @table_qualifier    varchar(32) = null,
  622.                  @index_name        varchar(32) = '%',
  623.                  @is_unique         char(1) = 'N',
  624.                  @accuracy            char(1) = 'Q')
  625. AS
  626.     DECLARE @indid                int
  627.     DECLARE @lastindid            int
  628.     DECLARE @table_id            int
  629.     DECLARE @full_table_name    char(70)
  630.  
  631.     if @table_qualifier is not null
  632.     begin
  633.         if db_name() != @table_qualifier
  634.         begin    /* If qualifier doesn't match current database */
  635.             print "Table qualifier must be name of current database"
  636.             return
  637.         end
  638.     end
  639.  
  640.     if @accuracy not in ('Q','E')
  641.        begin
  642.           print "Invalid value - please enter either 'Q' or 'E' for accuracy."
  643.           return
  644.        end
  645.  
  646.     if @@trancount != 0
  647.     begin    /* If inside a transaction */
  648.         raiserror 20001 "stored procedure sp_statistics can not be run while in a transaction"
  649.         return
  650.     end
  651.     create table #TmpIndex(
  652.                 table_qualifier varchar(32),
  653.                 table_owner     varchar(32),
  654.                 table_name      varchar(32),
  655.                 index_qualifier varchar(32) null,
  656.                 index_name      varchar(32) null,
  657.                 non_unique      smallint null,
  658.                 type            smallint,
  659.                 seq_in_index    smallint null,
  660.                 column_name     varchar(32) null,
  661.                 collation       char(1) null,
  662.                 index_id        int null,
  663.                 cardinality     int null,
  664.                 pages           int null,
  665.                 status          smallint)
  666.     if @table_owner is null
  667.     begin    /* If unqualified table name */
  668.         SELECT @full_table_name = @table_name
  669.     end
  670.     else
  671.     begin    /* Qualified table name */
  672.         SELECT @full_table_name = @table_owner + '.' + @table_name
  673.     end
  674.     /*    Get Object ID */
  675.     SELECT @table_id = object_id(@full_table_name)
  676.  
  677.     /*    Start at lowest index id */
  678.     SELECT @indid = min(indid)
  679.     FROM sysindexes
  680.     WHERE id = @table_id
  681.         AND indid > 0
  682.         AND indid < 255
  683.  
  684.     WHILE @indid != NULL
  685.     BEGIN
  686.         INSERT #TmpIndex    /* Add all columns that are in index */
  687.             SELECT
  688.                 DB_NAME(),                                /* table_qualifier */
  689.                 USER_NAME(o.uid),                        /* table_owner       */
  690.                 o.name,                                 /* table_name       */
  691.                 o.name,                                 /* index_qualifier */
  692.                 x.name,                                 /* index_name       */
  693.                 0,                                        /* non_unique       */
  694.                 1,                                        /* SQL_INDEX_CLUSTERED */
  695.                 colid,                                    /* seq_in_index    */
  696.                 INDEX_COL(@full_table_name,indid,colid),/* column_name       */
  697.                 "A",                                    /* collation       */
  698.                 @indid,                                 /* index_id        */
  699.                 rowcnt(x.doampg),                        /* cardinality       */
  700.                 data_pgs(x.id,doampg),                    /* pages           */
  701.                 x.status                                /* status           */
  702.             FROM sysindexes x, syscolumns c, sysobjects o
  703.             WHERE
  704.                 x.id = @table_id
  705.                 AND x.id = o.id
  706.                 AND x.id = c.id
  707.                 AND c.colid < keycnt+(x.status&16)/16
  708.                 AND x.indid = @indid
  709.         /*
  710.         **      Now move @indid to the next index.
  711.         */
  712.         SELECT @lastindid = @indid
  713.         SELECT @indid = NULL
  714.  
  715.         SELECT @indid = min(indid)
  716.         FROM sysindexes
  717.         WHERE id = @table_id
  718.             AND indid > @lastindid
  719.             AND indid < 255
  720.     END
  721.  
  722.     UPDATE #TmpIndex
  723.         SET non_unique = 1
  724.         WHERE status&2 != 2 /* If non-unique index */
  725.     UPDATE #TmpIndex
  726.         SET
  727.             type = 3,            /* SQL_INDEX_OTHER */
  728.             cardinality = NULL,
  729.             pages = NULL
  730.         WHERE index_id > 1    /* If non-clustered index */
  731.  
  732.     /* now add row for table statistics */
  733.     INSERT #TmpIndex
  734.         SELECT
  735.             DB_NAME(),                /* table_qualifier */
  736.             USER_NAME(o.uid),        /* table_owner       */
  737.             o.name,                 /* table_name       */
  738.             null,                    /* index_qualifier */
  739.             null,                    /* index_name       */
  740.             null,                    /* non_unique       */
  741.             0,                        /* SQL_TABLE_STAT  */
  742.             null,                    /* seq_in_index    */
  743.             null,                    /* column_name       */
  744.             null,                    /* collation       */
  745.             0,                        /* index_id        */
  746.             rowcnt(x.doampg),        /* cardinality       */
  747.             data_pgs(x.id,doampg),    /* pages           */
  748.             0                        /* status           */
  749.         FROM sysindexes x, sysobjects o
  750.         WHERE o.id = @table_id
  751.             AND x.id = o.id
  752.             AND (x.indid = 0 or x.indid = 1)    /*    If there are no indexes */
  753.                                                 /*    then table stats are in */
  754.                                                 /*    a row with indid =0        */
  755.  
  756.     if @is_unique != 'Y'    /* If all indexes desired */
  757.         SELECT
  758.             table_qualifier,
  759.             table_owner,
  760.             table_name,
  761.             non_unique,
  762.             index_qualifier,
  763.             index_name,
  764.             type,
  765.             seq_in_index,
  766.             column_name,
  767.             collation,
  768.             cardinality,
  769.             pages,
  770.             filter_condition = convert(varchar(128),null)
  771.         FROM #TmpIndex
  772.         WHERE
  773.             index_name like @index_name /* If matching name */
  774.             or index_name is null        /* If SQL_TABLE_STAT row */
  775.         ORDER BY non_unique, type, index_name, seq_in_index
  776.     else                    /* If only unique indexes desired */
  777.         SELECT
  778.             table_qualifier,
  779.             table_owner,
  780.             table_name,
  781.             non_unique,
  782.             index_qualifier,
  783.             index_name,
  784.             type,
  785.             seq_in_index,
  786.             column_name,
  787.             collation,
  788.             cardinality,
  789.             pages,
  790.             filter_condition = convert(varchar(128),null)
  791.         FROM #TmpIndex
  792.         WHERE
  793.             (non_unique = 0             /* If unique */
  794.                 or non_unique is NULL)    /* If SQL_TABLE_STAT row */
  795.             and (index_name like @index_name    /* If matching name */
  796.                 or index_name is null)    /* If SQL_TABLE_STAT row */
  797.         ORDER BY non_unique, type, index_name, seq_in_index
  798.  
  799.     DROP TABLE #TmpIndex
  800. go
  801.  
  802. if object_id('#TmpIndex') != null
  803.     drop table #TmpIndex
  804. dump tran master with truncate_only
  805. go
  806.  
  807.  
  808. if  (charindex('4.8', @@version) != 0
  809.     or charindex('4.9', @@version) != 0)
  810. begin
  811.     print ""
  812.     print ""
  813.     print "Warning:"
  814.     print "you are installing the stored procedures "
  815.     print "on SQL Server with version 4.8 or greater. "
  816.     print "Ignore the following error."
  817. end
  818. go
  819.  
  820. /*    This procedure is for < 4.8 servers */
  821. CREATE PROCEDURE sp_statistics (
  822.                  @table_name        varchar(32),
  823.                  @table_owner        varchar(32) = null,
  824.                  @table_qualifier    varchar(32) = null,
  825.                  @index_name        varchar(32) = '%',
  826.                  @is_unique         char(1) = 'N',
  827.                  @accuracy            char(1) = 'Q')
  828. AS
  829.     DECLARE @indid                int
  830.     DECLARE @lastindid            int
  831.     DECLARE @table_id            int
  832.     DECLARE @full_table_name    char(70)
  833.  
  834.     if @table_qualifier is not null
  835.     begin
  836.         if db_name() != @table_qualifier
  837.         begin    /* If qualifier doesn't match current database */
  838.             print "Table qualifier must be name of current database"
  839.             return
  840.         end
  841.     end
  842.  
  843.     if @accuracy not in ('Q','E')
  844.        begin
  845.           print "Invalid value - please enter either 'Q' or 'E' for accuracy."
  846.           return
  847.        end
  848.  
  849.     if @@trancount != 0
  850.     begin    /* If inside a transaction */
  851.         raiserror 20001 "stored procedure sp_statistics can not be run while in a transaction"
  852.         return
  853.     end
  854.     create table #TmpIndex(
  855.                 table_qualifier varchar(32),
  856.                 table_owner     varchar(32),
  857.                 table_name      varchar(32),
  858.                 index_qualifier varchar(32) null,
  859.                 index_name      varchar(32) null,
  860.                 non_unique      smallint null,
  861.                 type            smallint,
  862.                 seq_in_index    smallint null,
  863.                 column_name     varchar(32) null,
  864.                 collation       char(1) null,
  865.                 index_id        int null,
  866.                 cardinality     int null,
  867.                 pages           int null,
  868.                 status          smallint)
  869.     if @table_owner is null
  870.     begin    /* If unqualified table name */
  871.         SELECT @full_table_name = @table_name
  872.     end
  873.     else
  874.     begin    /* Qualified table name */
  875.         SELECT @full_table_name = @table_owner + '.' + @table_name
  876.     end
  877.     /*    Get Object ID */
  878.     SELECT @table_id = object_id(@full_table_name)
  879.  
  880.     /*    Start at lowest index id */
  881.     SELECT @indid = min(indid)
  882.     FROM sysindexes
  883.     WHERE id = @table_id
  884.         AND indid > 0
  885.         AND indid < 255
  886.  
  887.     WHILE @indid != NULL
  888.     BEGIN
  889.         INSERT #TmpIndex    /* Add all columns that are in index */
  890.             SELECT
  891.                 DB_NAME(),                                /* table_qualifier */
  892.                 USER_NAME(o.uid),                        /* table_owner       */
  893.                 o.name,                                 /* table_name       */
  894.                 o.name,                                 /* index_qualifier */
  895.                 x.name,                                 /* index_name       */
  896.                 0,                                        /* non_unique       */
  897.                 1,                                        /* SQL_INDEX_CLUSTERED */
  898.                 colid,                                    /* seq_in_index    */
  899.                 INDEX_COL(@full_table_name,indid,colid),/* column_name       */
  900.                 "A",                                    /* collation       */
  901.                 @indid,                                 /* index_id        */
  902.                 x.rows,                                 /* cardinality       */
  903.                 x.dpages,                                /* pages           */
  904.                 x.status                                /* status            */
  905.             FROM sysindexes x, syscolumns c, sysobjects o
  906.             WHERE
  907.                 x.id = @table_id
  908.                 AND x.id = o.id
  909.                 AND x.id = c.id
  910.                 AND c.colid < keycnt+(x.status&16)/16
  911.                 AND x.indid = @indid
  912.         /*
  913.         **      Now move @indid to the next index.
  914.         */
  915.         SELECT @lastindid = @indid
  916.         SELECT @indid = NULL
  917.  
  918.         SELECT @indid = min(indid)
  919.         FROM sysindexes
  920.         WHERE id = @table_id
  921.             AND indid > @lastindid
  922.             AND indid < 255
  923.     END
  924.  
  925.     UPDATE #TmpIndex
  926.         SET non_unique = 1
  927.         WHERE status&2 != 2 /* If non-unique index */
  928.     UPDATE #TmpIndex
  929.         SET
  930.             type = 3,            /* SQL_INDEX_OTHER */
  931.             cardinality = NULL,
  932.             pages = NULL
  933.         WHERE index_id > 1    /* If non-clustered index */
  934.  
  935.     /* now add row for table statistics */
  936.     INSERT #TmpIndex
  937.         SELECT
  938.             DB_NAME(),                /* table_qualifier */
  939.             USER_NAME(o.uid),        /* table_owner       */
  940.             o.name,                 /* table_name       */
  941.             null,                    /* index_qualifier */
  942.             null,                    /* index_name       */
  943.             null,                    /* non_unique       */
  944.             0,                        /* SQL_TABLE_STAT  */
  945.             null,                    /* seq_in_index    */
  946.             null,                    /* column_name       */
  947.             null,                    /* collation       */
  948.             0,                        /* index_id        */
  949.             x.rows,                 /* cardinality       */
  950.             x.dpages,                /* pages           */
  951.             0                        /* status           */
  952.         FROM sysindexes x, sysobjects o
  953.         WHERE o.id = @table_id
  954.             AND x.id = o.id
  955.             AND (x.indid = 0 or x.indid = 1)    /*    If there are no indexes */
  956.                                                 /*    then table stats are in */
  957.                                                 /*    a row with indid =0        */
  958.  
  959.     if @is_unique != 'Y'    /* If all indexes desired */
  960.         SELECT
  961.             table_qualifier,
  962.             table_owner,
  963.             table_name,
  964.             non_unique,
  965.             index_qualifier,
  966.             index_name,
  967.             type,
  968.             seq_in_index,
  969.             column_name,
  970.             collation,
  971.             cardinality,
  972.             pages,
  973.             filter_condition = convert(varchar(128),null)
  974.         FROM #TmpIndex
  975.         WHERE
  976.             index_name like @index_name /* If matching name */
  977.             or index_name is null        /* If SQL_TABLE_STAT row */
  978.         ORDER BY non_unique, type, index_name, seq_in_index
  979.     else                    /* If only unique indexes desired */
  980.         SELECT
  981.             table_qualifier,
  982.             table_owner,
  983.             table_name,
  984.             non_unique,
  985.             index_qualifier,
  986.             index_name,
  987.             type,
  988.             seq_in_index,
  989.             column_name,
  990.             collation,
  991.             cardinality,
  992.             pages,
  993.             filter_condition = convert(varchar(128),null)
  994.         FROM #TmpIndex
  995.         WHERE
  996.             (non_unique = 0             /* If unique */
  997.                 or non_unique is NULL)    /* If SQL_TABLE_STAT row */
  998.             and (index_name like @index_name    /* If matching name */
  999.                 or index_name is null)    /* If SQL_TABLE_STAT row */
  1000.         ORDER BY non_unique, type, index_name, seq_in_index
  1001.  
  1002.     DROP TABLE #TmpIndex
  1003. go
  1004.  
  1005. grant execute on sp_statistics to public
  1006. go
  1007.  
  1008. dump tran master with truncate_only
  1009. go
  1010.  
  1011.  
  1012. print "creating sp_columns"
  1013. go
  1014.  
  1015. CREATE PROCEDURE sp_columns (
  1016.                  @table_name        varchar(32),
  1017.                  @table_owner        varchar(32) = null,
  1018.                  @table_qualifier    varchar(32) = null,
  1019.                  @column_name        varchar(32) = null )
  1020. AS
  1021.     DECLARE @full_table_name    char(70)
  1022.     DECLARE @table_id int
  1023.  
  1024.     if @column_name is null /*    If column name not supplied, match all */
  1025.         select @column_name = '%'
  1026.     if @table_qualifier is not null
  1027.     begin
  1028.         if db_name() != @table_qualifier
  1029.         begin    /* If qualifier doesn't match current database */
  1030.             print "Table qualifier must be name of current database"
  1031.             return
  1032.         end
  1033.     end
  1034.     if @table_name is null
  1035.     begin    /*    If table name not supplied, match all */
  1036.         select @table_name = '%'
  1037.     end
  1038.     if @table_owner is null
  1039.     begin    /* If unqualified table name */
  1040.         SELECT @full_table_name = @table_name
  1041.     end
  1042.     else
  1043.     begin    /* Qualified table name */
  1044.         SELECT @full_table_name = @table_owner + '.' + @table_name
  1045.     end
  1046.  
  1047.     /*    Get Object ID */
  1048.     SELECT @table_id = object_id(@full_table_name)
  1049.     if ((charindex('%',@full_table_name) = 0) and
  1050.         (charindex('_',@full_table_name) = 0)  and
  1051.         @table_id != 0)
  1052.     begin
  1053.         /* this block is for the case where there is no pattern
  1054.              matching required for the table name */
  1055.         SELECT    /* INTn, FLOATn, DATETIMEn and MONEYn types */
  1056.             table_qualifier = DB_NAME(),
  1057.             table_owner = USER_NAME(o.uid),
  1058.             table_name = o.name,
  1059.             column_name = c.name,
  1060.             data_type = d.data_type+convert(smallint,
  1061.                         isnull(d.aux,
  1062.                         ascii(substring("666AAA@@@CB??GG",
  1063.                         2*(d.ss_dtype%35+1)+2-8/c.length,1))
  1064.                         -60)),
  1065.             type_name = rtrim(substring(d.type_name,
  1066.                         1+isnull(d.aux,
  1067.                         ascii(substring("III<<<MMMI<<A<A",
  1068.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  1069.                         1))-60), 13)),
  1070.             precision = isnull(d.data_precision, convert(int,c.length))
  1071.                         +isnull(d.aux, convert(int,
  1072.                         ascii(substring("???AAAFFFCKFOLS",
  1073.                         2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
  1074.             length = isnull(d.length, convert(int,c.length)) +convert(int,
  1075.                         isnull(d.aux,
  1076.                         ascii(substring("AAA<BB<DDDHJSPP",
  1077.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  1078.                         1))-64)),
  1079.             scale = d.numeric_scale +convert(smallint,
  1080.                         isnull(d.aux,
  1081.                         ascii(substring("<<<<<<<<<<<<<<?",
  1082.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  1083.                         1))-60)),
  1084.             radix = d.numeric_radix,
  1085.             nullable =    /* set nullability from status flag */
  1086.                 convert(smallint, convert(bit, c.status&8)),
  1087.             remarks = convert(varchar(254),null),    /* Remarks are NULL */
  1088.             ss_data_type = c.type,
  1089.             colid = c.colid
  1090.         FROM
  1091.             syscolumns c,
  1092.             sysobjects o,
  1093.             master.dbo.spt_datatype_info d,
  1094.             systypes t
  1095.         WHERE
  1096.             o.id = @table_id
  1097.             AND c.id = o.id
  1098.             AND c.type = d.ss_dtype
  1099.             AND c.name like @column_name
  1100.             AND d.ss_dtype IN (111, 109, 38, 110)    /* Just *N types */
  1101.             AND c.usertype < 100                    /* No user defined types */
  1102.         UNION
  1103.         SELECT    /* All other types including user data types */
  1104.             table_qualifier = DB_NAME(),
  1105.             table_owner = USER_NAME(o.uid),
  1106.             table_name = o.name,
  1107.             column_name = c.name,
  1108.             data_type = convert(smallint,
  1109.                 /*    Map systypes.type to ODBC type */
  1110.                 /*        SS-Type         "                     1          "*/
  1111.                 /*                        "33 3 3     4 44 5 5 2 5 55666"*/
  1112.                 /*                        "45 7 9        5 78 0 2 2 6 89012"*/
  1113.                         ascii(substring("8;<9<H<<<<<:<=6<5<A<?<@<GC?GB",
  1114.                         t.type%34+1,1))-60),
  1115.             type_name = t.name,
  1116.             precision = isnull(d.data_precision, convert(int,c.length))
  1117.                         +isnull(d.aux, convert(int,
  1118.                         ascii(substring("???AAAFFFCKFOLS",
  1119.                         2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
  1120.             length = isnull(d.length, convert(int,c.length)) +convert(int,
  1121.                         isnull(d.aux,
  1122.                         ascii(substring("AAA<BB<DDDHJSPP",
  1123.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  1124.                         1))-64)),
  1125.             scale = d.numeric_scale +convert(smallint,
  1126.                         isnull(d.aux,
  1127.                         ascii(substring("<<<<<<<<<<<<<<?",
  1128.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  1129.                         1))-60)),
  1130.             radix = d.numeric_radix,
  1131.             nullable =    /* set nullability from status flag */
  1132.                 convert(smallint, convert(bit, c.status&8)),
  1133.             remarks = convert(varchar(254),null),    /* Remarks are NULL */
  1134.             ss_data_type = c.type,
  1135.             colid = c.colid
  1136.         FROM
  1137.             syscolumns c,
  1138.             sysobjects o,
  1139.             master.dbo.spt_datatype_info d,
  1140.             systypes t
  1141.         WHERE
  1142.             o.id = @table_id
  1143.             AND c.id = o.id
  1144.             AND c.type = d.ss_dtype
  1145.             AND c.usertype *= t.usertype
  1146.             AND c.name like @column_name
  1147.             AND (d.ss_dtype NOT IN (111, 109, 38, 110)    /* No *N types */
  1148.                 OR c.usertype >= 100)                    /* User defined types */
  1149.         ORDER BY colid
  1150.     end
  1151.     else
  1152.     begin
  1153.         /* this block is for the case where there IS pattern
  1154.              matching done on the table name */
  1155.         if @table_owner is null /*    If owner not supplied, match all */
  1156.             select @table_owner = '%'
  1157.         SELECT    /* INTn, FLOATn, DATETIMEn and MONEYn types */
  1158.             table_qualifier = DB_NAME(),
  1159.             table_owner = USER_NAME(o.uid),
  1160.             table_name = o.name,
  1161.             column_name = c.name,
  1162.             data_type = d.data_type+convert(smallint,
  1163.                         isnull(d.aux,
  1164.                         ascii(substring("666AAA@@@CB??GG",
  1165.                         2*(d.ss_dtype%35+1)+2-8/c.length,1))
  1166.                         -60)),
  1167.             type_name = rtrim(substring(d.type_name,
  1168.                         1+isnull(d.aux,
  1169.                         ascii(substring("III<<<MMMI<<A<A",
  1170.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  1171.                         1))-60), 13)),
  1172.             precision = isnull(d.data_precision, convert(int,c.length))
  1173.                         +isnull(d.aux, convert(int,
  1174.                         ascii(substring("???AAAFFFCKFOLS",
  1175.                         2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
  1176.             length = isnull(d.length, convert(int,c.length)) +convert(int,
  1177.                         isnull(d.aux,
  1178.                         ascii(substring("AAA<BB<DDDHJSPP",
  1179.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  1180.                         1))-64)),
  1181.             scale = d.numeric_scale +convert(smallint,
  1182.                         isnull(d.aux,
  1183.                         ascii(substring("<<<<<<<<<<<<<<?",
  1184.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  1185.                         1))-60)),
  1186.             radix = d.numeric_radix,
  1187.             nullable =    /* set nullability from status flag */
  1188.                 convert(smallint, convert(bit, c.status&8)),
  1189.             remarks = convert(varchar(254),null),    /* Remarks are NULL */
  1190.             ss_data_type = c.type,
  1191.             colid = c.colid
  1192.         FROM
  1193.             syscolumns c,
  1194.             sysobjects o,
  1195.             master.dbo.spt_datatype_info d,
  1196.             systypes t
  1197.         WHERE
  1198.             o.name like @table_name
  1199.             AND user_name(o.uid) like @table_owner
  1200.             AND o.id = c.id
  1201.             AND c.type = d.ss_dtype
  1202.             AND o.type != 'P'
  1203.             AND c.name like @column_name
  1204.             AND d.ss_dtype IN (111, 109, 38, 110)    /* Just *N types */
  1205.         UNION
  1206.         SELECT    /* All other types including user data types */
  1207.             table_qualifier = DB_NAME(),
  1208.             table_owner = USER_NAME(o.uid),
  1209.             table_name = o.name,
  1210.             column_name = c.name,
  1211.             data_type = convert(smallint,
  1212.                 /*    Map systypes.type to ODBC type */
  1213.                 /*        SS-Type         "                     1          "*/
  1214.                 /*                        "33 3 3     4 44 5 5 2 5 55666"*/
  1215.                 /*                        "45 7 9        5 78 0 2 2 6 89012"*/
  1216.                         ascii(substring("8;<9<H<<<<<:<=6<5<A<?<@<GC?GB",
  1217.                         t.type%34+1,1))-60),
  1218.             type_name = t.name,
  1219.             precision = isnull(d.data_precision, convert(int,c.length))
  1220.                         +isnull(d.aux, convert(int,
  1221.                         ascii(substring("???AAAFFFCKFOLS",
  1222.                         2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
  1223.             length = isnull(d.length, convert(int,c.length)) +convert(int,
  1224.                         isnull(d.aux,
  1225.                         ascii(substring("AAA<BB<DDDHJSPP",
  1226.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  1227.                         1))-64)),
  1228.             scale = d.numeric_scale +convert(smallint,
  1229.                         isnull(d.aux,
  1230.                         ascii(substring("<<<<<<<<<<<<<<?",
  1231.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  1232.                         1))-60)),
  1233.             radix = d.numeric_radix,
  1234.             nullable =    /* set nullability from status flag */
  1235.                 convert(smallint, convert(bit, c.status&8)),
  1236.             remarks  = convert(varchar(254),null),
  1237.             ss_data_type = c.type,
  1238.             colid = c.colid
  1239.         FROM
  1240.             syscolumns c,
  1241.             sysobjects o,
  1242.             master.dbo.spt_datatype_info d,
  1243.             systypes t
  1244.         WHERE
  1245.             o.name like @table_name
  1246.             AND user_name(o.uid) like @table_owner
  1247.             AND o.id = c.id
  1248.             AND c.type = d.ss_dtype
  1249.             AND c.usertype *= t.usertype
  1250.             AND o.type != 'P'
  1251.             AND c.name like @column_name
  1252.             AND d.ss_dtype NOT IN (111, 109, 38, 110)    /* No *N types */
  1253.         ORDER BY table_owner, table_name, colid
  1254.     end
  1255. go
  1256.  
  1257. grant execute on sp_columns to public
  1258. go
  1259.  
  1260. dump tran master with truncate_only
  1261. go
  1262. print "creating sp_fkeys"
  1263. go
  1264.  
  1265. CREATE PROCEDURE sp_fkeys(
  1266.                @pktable_name        varchar(32) = null,
  1267.                @pktable_owner        varchar(32) = null,
  1268.                @pktable_qualifier    varchar(32) = null,
  1269.                @fktable_name        varchar(32) = null,
  1270.                @fktable_owner        varchar(32) = null,
  1271.                @fktable_qualifier    varchar(32) = null )
  1272. as
  1273.     declare    @order_by_pk int
  1274.  
  1275.     select  @order_by_pk = 0
  1276.  
  1277.     if (@pktable_name is null) and (@fktable_name is null)
  1278.     begin    /* If neither primary key nor foreign key table names given */
  1279.         print "pk table name or fk table name must be given"
  1280.         return
  1281.     end
  1282.     if @fktable_qualifier is not null
  1283.     begin
  1284.         if db_name() != @fktable_qualifier
  1285.         begin    /* If qualifier doesn't match current database */
  1286.             print "Foreign Key Table qualifier must be name of current database"
  1287.             return
  1288.         end
  1289.     end
  1290.     if @pktable_qualifier is not null
  1291.     begin
  1292.         if db_name() != @pktable_qualifier
  1293.         begin    /* If qualifier doesn't match current database */
  1294.             print "Primary Key Table qualifier must be name of current database"
  1295.             return
  1296.         end
  1297.     end
  1298.  
  1299.     if @pktable_name is null
  1300.     begin /*  If table name not supplied, match all */
  1301.         select @pktable_name = '%'
  1302.         select @order_by_pk = 1
  1303.     end
  1304.     if @pktable_owner is null    /*    If PK owner not supplied, match all */
  1305.         select @pktable_owner = '%'
  1306.     if @fktable_name is null    /*    If table name not supplied, match all */
  1307.         select @fktable_name = '%'
  1308.     if @fktable_owner is null    /*    If FK owner not supplied, match all */
  1309.         select @fktable_owner = '%'
  1310.  
  1311.     if @@trancount != 0
  1312.     begin    /* If inside a transaction */
  1313.         raiserror 20001 "catalog procedure sp_fkeys can not be run in a transaction"
  1314.     return
  1315.     end
  1316.     create table #fkeys(
  1317.              pktable_qualifier    varchar(32),
  1318.              pktable_owner        varchar(32),
  1319.              pktable_name       varchar(32),
  1320.              pkcolumn_name      varchar(32),
  1321.              fktable_qualifier    varchar(32),
  1322.              fktable_owner        varchar(32),
  1323.              fktable_name       varchar(32),
  1324.              fkcolumn_name        varchar(32),
  1325.              key_seq            smallint)
  1326.  
  1327.     /*    SQL Server supports upto 8 PK/FK relationships between 2 tables */
  1328.     /*    Process syskeys for each relationship */
  1329.     /*    The inserts below adds a row to the temp table for each of the
  1330.         8 possible relationships */
  1331.     insert into #fkeys
  1332.         select
  1333.             db_name(),
  1334.             user_name(o1.uid),
  1335.             object_name(k.depid),
  1336.             c2.name,
  1337.             db_name(),
  1338.             user_name(o2.uid),
  1339.             object_name(k.id),
  1340.             c1.name,
  1341.             1
  1342.         from
  1343.             syskeys k, syscolumns c1, syscolumns c2,sysobjects o1, sysobjects o2
  1344.         where
  1345.             c1.id = k.id
  1346.             and k.type = 2    /* Foreign type key */
  1347.             and c1.colid = k.key1
  1348.             and c2.id = k.depid
  1349.             and c2.colid = k.depkey1
  1350.             and o1.id = k.depid
  1351.             and o2.id = k.id
  1352.     union
  1353.         select
  1354.             db_name(),
  1355.             user_name(o1.uid),
  1356.             object_name(k.depid),
  1357.             c2.name,
  1358.             db_name(),
  1359.             user_name(o2.uid),
  1360.             object_name(k.id),
  1361.             c1.name,
  1362.             2
  1363.         from
  1364.             syskeys k, syscolumns c1, syscolumns c2,sysobjects o1, sysobjects o2
  1365.         where
  1366.             c1.id = k.id
  1367.             and k.type = 2    /* Foreign type key */
  1368.             and c1.colid = k.key2
  1369.             and c2.id = k.depid
  1370.             and c2.colid = k.depkey2
  1371.             and o1.id = k.depid
  1372.             and o2.id = k.id
  1373.     union
  1374.         select
  1375.             db_name(),
  1376.             user_name(o1.uid),
  1377.             object_name(k.depid),
  1378.             c2.name,
  1379.             db_name(),
  1380.             user_name(o2.uid),
  1381.             object_name(k.id),
  1382.             c1.name,
  1383.             3
  1384.         from
  1385.             syskeys k, syscolumns c1, syscolumns c2,sysobjects o1, sysobjects o2
  1386.         where
  1387.             c1.id = k.id
  1388.             and k.type = 2    /* Foreign type key */
  1389.             and c1.colid = k.key3
  1390.             and c2.id = k.depid
  1391.             and c2.colid = k.depkey3
  1392.             and o1.id = k.depid
  1393.             and o2.id = k.id
  1394.     union
  1395.         select
  1396.             db_name(),
  1397.             user_name(o1.uid),
  1398.             object_name(k.depid),
  1399.             c2.name,
  1400.             db_name(),
  1401.             user_name(o2.uid),
  1402.             object_name(k.id),
  1403.             c1.name,
  1404.             4
  1405.         from
  1406.             syskeys k, syscolumns c1, syscolumns c2,sysobjects o1, sysobjects o2
  1407.         where
  1408.             c1.id = k.id
  1409.             and k.type = 2    /* Foreign type key */
  1410.             and c1.colid = k.key4
  1411.             and c2.id = k.depid
  1412.             and c2.colid = k.depkey4
  1413.             and o1.id = k.depid
  1414.             and o2.id = k.id
  1415.     union
  1416.         select
  1417.             db_name(),
  1418.             user_name(o1.uid),
  1419.             object_name(k.depid),
  1420.             c2.name,
  1421.             db_name(),
  1422.             user_name(o2.uid),
  1423.             object_name(k.id),
  1424.             c1.name,
  1425.             5
  1426.         from
  1427.             syskeys k, syscolumns c1, syscolumns c2,sysobjects o1, sysobjects o2
  1428.         where
  1429.             c1.id = k.id
  1430.             and k.type = 2    /* Foreign type key */
  1431.             and c1.colid = k.key5
  1432.             and c2.id = k.depid
  1433.             and c2.colid = k.depkey5
  1434.             and o1.id = k.depid
  1435.             and o2.id = k.id
  1436.     union
  1437.         select
  1438.             db_name(),
  1439.             user_name(o1.uid),
  1440.             object_name(k.depid),
  1441.             c2.name,
  1442.             db_name(),
  1443.             user_name(o2.uid),
  1444.             object_name(k.id),
  1445.             c1.name,
  1446.             6
  1447.         from
  1448.             syskeys k, syscolumns c1, syscolumns c2,sysobjects o1, sysobjects o2
  1449.         where
  1450.             c1.id = k.id
  1451.             and k.type = 2    /* Foreign type key */
  1452.             and c1.colid = k.key6
  1453.             and c2.id = k.depid
  1454.             and c2.colid = k.depkey6
  1455.             and o1.id = k.depid
  1456.             and o2.id = k.id
  1457.     union
  1458.         select
  1459.             db_name(),
  1460.             user_name(o1.uid),
  1461.             object_name(k.depid),
  1462.             c2.name,
  1463.             db_name(),
  1464.             user_name(o2.uid),
  1465.             object_name(k.id),
  1466.             c1.name,
  1467.             7
  1468.         from
  1469.             syskeys k, syscolumns c1, syscolumns c2,sysobjects o1, sysobjects o2
  1470.         where
  1471.             c1.id = k.id
  1472.             and k.type = 2    /* Foreign type key */
  1473.             and c1.colid = k.key7
  1474.             and c2.id = k.depid
  1475.             and c2.colid = k.depkey7
  1476.             and o1.id = k.depid
  1477.             and o2.id = k.id
  1478.     union
  1479.         select
  1480.             db_name(),
  1481.             user_name(o1.uid),
  1482.             object_name(k.depid),
  1483.             c2.name,
  1484.             db_name(),
  1485.             user_name(o2.uid),
  1486.             object_name(k.id),
  1487.             c1.name,
  1488.             8
  1489.         from
  1490.             syskeys k, syscolumns c1, syscolumns c2,sysobjects o1, sysobjects o2
  1491.         where
  1492.             c1.id = k.id
  1493.             and k.type = 2    /* Foreign type key */
  1494.             and c1.colid = k.key8
  1495.             and c2.id = k.depid
  1496.             and c2.colid = k.depkey8
  1497.             and o1.id = k.depid
  1498.             and o2.id = k.id
  1499.  
  1500.     if @order_by_pk = 1 /*    If order by PK fields */
  1501.         select
  1502.             pktable_qualifier,
  1503.             pktable_owner,
  1504.             pktable_name,
  1505.             pkcolumn_name,
  1506.             fktable_qualifier,
  1507.             fktable_owner,
  1508.             fktable_name,
  1509.             fkcolumn_name,
  1510.             key_seq,
  1511.             update_rule = convert(smallint, null),
  1512.             delete_rule = convert(smallint,null),
  1513.             fk_name = convert(varchar(32),null),
  1514.             pk_name = convert(varchar(32),null)
  1515.         from #fkeys
  1516.         where fktable_name like @fktable_name
  1517.             and fktable_owner like @fktable_owner
  1518.             and pktable_name  like @pktable_name
  1519.             and pktable_owner like @pktable_owner
  1520.         order by pktable_qualifier, pktable_owner, pktable_name, key_seq
  1521.     else        /*    Order by FK fields */
  1522.         select
  1523.             pktable_qualifier,
  1524.             pktable_owner,
  1525.             pktable_name,
  1526.             pkcolumn_name,
  1527.             fktable_qualifier,
  1528.             fktable_owner,
  1529.             fktable_name,
  1530.             fkcolumn_name,
  1531.             key_seq,
  1532.             update_rule = convert(smallint,null),
  1533.             delete_rule = convert(smallint,null),
  1534.             fk_name = convert(varchar(32),null),
  1535.             pk_name = convert(varchar(32),null)
  1536.         from #fkeys
  1537.         where fktable_name like @fktable_name
  1538.             and fktable_owner like @fktable_owner
  1539.             and pktable_name  like @pktable_name
  1540.             and pktable_owner like @pktable_owner
  1541.         order by fktable_qualifier, fktable_owner, fktable_name, key_seq
  1542. go
  1543.  
  1544. grant execute on sp_fkeys to public
  1545. go
  1546. dump tran master with truncate_only
  1547. go
  1548.  
  1549. print "creating sp_pkeys"
  1550. go
  1551.  
  1552. CREATE PROCEDURE sp_pkeys(
  1553.                @table_name        varchar(32),
  1554.                @table_owner     varchar(32) = null,
  1555.                @table_qualifier varchar(32) = null )
  1556. as
  1557.     if @table_qualifier is not null
  1558.     begin
  1559.         if db_name() != @table_qualifier
  1560.         begin    /* If qualifier doesn't match current database */
  1561.             print "Table qualifier must be name of current database"
  1562.             return
  1563.         end
  1564.     end
  1565.     if @table_owner is null /*    If owner not supplied, match all */
  1566.         select @table_owner = '%'
  1567.     if @@trancount != 0
  1568.     begin    /* If inside a transaction */
  1569.         raiserror 20001 "catalog procedure sp_pkeys can not be run in a transaction"
  1570.         return
  1571.     end
  1572.  
  1573.     create table #pkeys(
  1574.              table_qualifier varchar(32),
  1575.              table_owner     varchar(32),
  1576.              table_name      varchar(32),
  1577.              column_name     varchar(32),
  1578.              key_seq         smallint)
  1579.  
  1580.     /*    SQL Server supports upto 8 PK/FK relationships between 2 tables */
  1581.     /*    Process syskeys for each relationship */
  1582.     /*    The inserts below adds a row to the temp table for each of the
  1583.         8 possible relationships */
  1584.     insert into #pkeys
  1585.         select
  1586.             db_name(),
  1587.             (select user_name(uid) from sysobjects o where o.id = k.id),
  1588.             object_name(k.id),
  1589.             c.name,
  1590.             1
  1591.         from
  1592.             syskeys k, syscolumns c
  1593.         where
  1594.             c.id = k.id
  1595.             and k.type = 1    /* Primary type key */
  1596.             and c.colid = k.key1
  1597.     if (@@rowcount = 0)
  1598.         goto done
  1599.  
  1600.     insert into #pkeys
  1601.         select
  1602.             db_name(),
  1603.             (select user_name(uid) from sysobjects o where o.id = k.id),
  1604.             object_name(k.id),
  1605.             c.name,
  1606.             2
  1607.         from
  1608.             syskeys k, syscolumns c
  1609.         where
  1610.             c.id = k.id
  1611.             and k.type = 1    /* Primary type key */
  1612.             and c.colid = key2
  1613.     if (@@rowcount = 0)
  1614.         goto done
  1615.  
  1616.     insert into #pkeys
  1617.         select
  1618.             db_name(),
  1619.             (select user_name(uid) from sysobjects o where o.id = k.id),
  1620.             object_name(k.id),
  1621.             c.name,
  1622.             3
  1623.         from
  1624.             syskeys k, syscolumns c
  1625.         where
  1626.             c.id = k.id
  1627.             and k.type = 1    /* Primary type key */
  1628.             and c.colid = key3
  1629.     if (@@rowcount = 0)
  1630.         goto done
  1631.  
  1632.     insert into #pkeys
  1633.         select
  1634.             db_name(),
  1635.             (select user_name(uid) from sysobjects o where o.id = k.id),
  1636.             object_name(k.id),
  1637.             c.name,
  1638.             4
  1639.         from
  1640.             syskeys k, syscolumns c
  1641.         where
  1642.             c.id = k.id
  1643.             and k.type = 1    /* Primary type key */
  1644.             and c.colid = key4
  1645.     if (@@rowcount = 0)
  1646.         goto done
  1647.  
  1648.     insert into #pkeys
  1649.         select
  1650.             db_name(),
  1651.             (select user_name(uid) from sysobjects o where o.id = k.id),
  1652.             object_name(k.id),
  1653.             c.name,
  1654.             5
  1655.         from
  1656.             syskeys k, syscolumns c
  1657.         where
  1658.             c.id = k.id
  1659.             and k.type = 1    /* Primary type key */
  1660.             and c.colid = key5
  1661.     if (@@rowcount = 0)
  1662.         goto done
  1663.  
  1664.     insert into #pkeys
  1665.         select
  1666.             db_name(),
  1667.             (select user_name(uid) from sysobjects o where o.id = k.id),
  1668.             object_name(k.id),
  1669.             c.name,
  1670.             6
  1671.         from
  1672.             syskeys k, syscolumns c
  1673.         where
  1674.             c.id = k.id
  1675.             and k.type = 1    /* Primary type key */
  1676.             and c.colid = key6
  1677.     if (@@rowcount = 0)
  1678.         goto done
  1679.  
  1680.     insert into #pkeys
  1681.         select
  1682.             db_name(),
  1683.             (select user_name(uid) from sysobjects o where o.id = k.id),
  1684.             object_name(k.id),
  1685.             c.name,
  1686.             7
  1687.         from
  1688.             syskeys k, syscolumns c
  1689.         where
  1690.             c.id = k.id
  1691.             and k.type = 1    /* Primary type key */
  1692.             and c.colid = key7
  1693.     if (@@rowcount = 0)
  1694.         goto done
  1695.  
  1696.     insert into #pkeys
  1697.          select
  1698.              db_name(),
  1699.              (select user_name(uid) from sysobjects o where o.id = k.id),
  1700.              object_name(k.id),
  1701.              c.name,
  1702.              8
  1703.          from
  1704.              syskeys k, syscolumns c
  1705.          where
  1706.              c.id = k.id
  1707.              and k.type = 1 /* Primary type key */
  1708.              and c.colid = key8
  1709.  
  1710.     done:
  1711.     select
  1712.         table_qualifier,
  1713.         table_owner,
  1714.         table_name,
  1715.         column_name,
  1716.         key_seq,
  1717.         pk_name = convert(varchar(32),null)
  1718.     from #pkeys
  1719.     where table_name like  @table_name
  1720.         and table_owner like @table_owner
  1721.     order by table_qualifier, table_owner, table_name, key_seq
  1722. go
  1723.  
  1724. grant execute on sp_pkeys to public
  1725. go
  1726.  
  1727. dump tran master with truncate_only
  1728. go
  1729.  
  1730. print "creating sp_stored_procedures"
  1731. go
  1732.  
  1733. create procedure sp_stored_procedures(
  1734.                         @sp_name        varchar(36) = null,
  1735.                         @sp_owner        varchar(32) = null,
  1736.                         @sp_qualifier    varchar(32) = null)
  1737. as
  1738.     declare @proc_type smallint
  1739.  
  1740.     if @sp_qualifier is not null
  1741.     begin
  1742.         if db_name() != @sp_qualifier
  1743.         begin
  1744.             if @sp_qualifier = ''
  1745.             begin
  1746.                 /* in this case, we need to return an empty result set */
  1747.                 /* because the user has requested a database with an empty name */
  1748.                 select @sp_name = ''
  1749.                 select @sp_owner = ''
  1750.             end else
  1751.             begin    /* If qualifier doesn't match current database */
  1752.                 print "Stored procedure qualifier must be name of current database"
  1753.                 return
  1754.             end
  1755.         end
  1756.     end
  1757.  
  1758.     if @sp_name is null
  1759.     begin  /*  If procedure name not supplied, match all */
  1760.         select @sp_name = '%'
  1761.     end
  1762.     else begin
  1763.         if (@sp_owner is null) and (charindex('%', @sp_name) = 0)
  1764.         begin
  1765.             if exists (select * from sysobjects
  1766.                 where uid = user_id()
  1767.                     and name = @sp_name
  1768.                     and type = 'P') /* Object type of Procedure */
  1769.             begin
  1770.                 select @sp_owner = user_name()
  1771.             end
  1772.         end
  1773.     end
  1774.     if @sp_owner is null    /*    If procedure owner not supplied, match all */
  1775.         select @sp_owner = '%'
  1776.  
  1777.     if  not (charindex('1.1', @@version) = 0
  1778.             and charindex('4.0', @@version) = 0)
  1779.             select @proc_type=1        /* Return 1 for pre 4.2 servers. */
  1780.     else
  1781.             select @proc_type=2        /* Return 2 for 4.2 and later servers. */
  1782.  
  1783.     select
  1784.         procedure_qualifier = db_name(),
  1785.         procedure_owner = user_name(o.uid),
  1786.         procedure_name = o.name +';'+ ltrim(str(p.number,5)),
  1787.         num_input_params = -1,    /* Constant since value unknown */
  1788.         num_output_params = -1, /* Constant since value unknown */
  1789.         num_result_sets = -1,    /* Constant since value unknown */
  1790.         remarks = convert(varchar(254),null),    /* Remarks are NULL */
  1791.         procedure_type = @proc_type
  1792.     from
  1793.         sysobjects o,sysprocedures p,sysusers u
  1794.     where
  1795.         o.name like @sp_name
  1796.         and p.sequence = 0
  1797.         and user_name(o.uid) like @sp_owner
  1798.         and o.type = 'P'        /* Object type of Procedure */
  1799.         and p.id = o.id
  1800.         and u.uid = user_id()    /* constrain sysusers uid for use in subquery */
  1801.         and (suser_id() = 1     /* User is the System Administrator */
  1802.             or o.uid = user_id()    /* User created the object */
  1803.             /* here's the magic... select the highest precedence of permissions in the order (user,group,public)  */
  1804.             or ((select max(((sign(uid)*abs(uid-16383))*2)+(protecttype&1))
  1805.              from sysprotects p
  1806.              /* outer join to correlate with all rows in sysobjects */
  1807.              where p.id =* o.id
  1808.                  /*  get rows for public,current user,user's group */
  1809.                  and (p.uid = 0 or p.uid = user_id() or p.uid =* u.gid)
  1810.                  /* check for SELECT,EXECUTE privilege */
  1811.                  and (action in (193,224)))&1    /* more magic...normalize GRANT */
  1812.             ) = 1     /* final magic...compare Grants    */
  1813.         )
  1814.     order by procedure_qualifier, procedure_owner, procedure_name
  1815. go
  1816. grant execute on sp_stored_procedures to public
  1817. go
  1818.  
  1819. dump tran master with truncate_only
  1820. go
  1821.  
  1822.  
  1823. print "creating sp_sproc_columns"
  1824. go
  1825.  
  1826. CREATE PROCEDURE sp_sproc_columns (
  1827.                  @procedure_name        varchar(36) = '%',
  1828.                  @procedure_owner        varchar(32) = null,
  1829.                  @procedure_qualifier    varchar(32) = null,
  1830.                  @column_name            varchar(32) = null )
  1831. AS
  1832.     DECLARE @group_num int
  1833.     DECLARE @semi_position int
  1834.     DECLARE @full_procedure_name    char(70)
  1835.     DECLARE @procedure_id int
  1836.  
  1837.     if @column_name is null /*    If column name not supplied, match all */
  1838.         select @column_name = '%'
  1839.     if @procedure_qualifier is not null
  1840.     begin
  1841.         if db_name() != @procedure_qualifier
  1842.         begin
  1843.             if @procedure_qualifier = ''
  1844.             begin
  1845.                 /* in this case, we need to return an empty result set */
  1846.                 /* because the user has requested a database with an empty name */
  1847.                 select @procedure_name = ''
  1848.                 select @procedure_owner = ''
  1849.             end
  1850.             else
  1851.             begin    /* If qualifier doesn't match current database */
  1852.                 print "Procedure qualifier must be name of current database"
  1853.                 return
  1854.             end
  1855.         end
  1856.     end
  1857.  
  1858.  
  1859.     /* first we need to extract the procedure group number, if one exists */
  1860.     select @semi_position = charindex(';',@procedure_name)
  1861.     if (@semi_position > 0)
  1862.     begin    /* If group number separator (;) found */
  1863.         select @group_num = convert(int,substring(@procedure_name, @semi_position + 1, 2))
  1864.         select @procedure_name = substring(@procedure_name, 1, @semi_position -1)
  1865.     end
  1866.     else
  1867.     begin    /* No group separator, so default to group number of 1 */
  1868.         select @group_num = 1
  1869.     end
  1870.  
  1871.     if @procedure_owner is null
  1872.     begin    /* If unqualified procedure name */
  1873.         SELECT @full_procedure_name = @procedure_name
  1874.     end
  1875.     else
  1876.     begin    /* Qualified procedure name */
  1877.         SELECT @full_procedure_name = @procedure_owner + '.' + @procedure_name
  1878.     end
  1879.  
  1880.     /*    Get Object ID */
  1881.     SELECT @procedure_id = object_id(@full_procedure_name)
  1882.     if ((charindex('%',@full_procedure_name) = 0) and
  1883.         (charindex('_',@full_procedure_name) = 0)  and
  1884.         @procedure_id != 0)
  1885.     begin
  1886.         /* this block is for the case where there is no pattern
  1887.             matching required for the procedure name */
  1888.         SELECT    /* INTn, FLOATn, DATETIMEn and MONEYn types */
  1889.             procedure_qualifier = DB_NAME(),
  1890.             procedure_owner = USER_NAME(o.uid),
  1891.             procedure_name = o.name +';'+ ltrim(str(c.number,5)),
  1892.             column_name = c.name,
  1893.             column_type = convert(smallint, 0),
  1894.             data_type = d.data_type+convert(smallint,
  1895.                         isnull(d.aux,
  1896.                         ascii(substring("666AAA@@@CB??GG",
  1897.                         2*(d.ss_dtype%35+1)+2-8/c.length,1))
  1898.                         -60)),
  1899.             type_name = rtrim(substring(d.type_name,
  1900.                         1+isnull(d.aux,
  1901.                         ascii(substring("III<<<MMMI<<A<A",
  1902.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  1903.                         1))-60), 13)),
  1904.             precision = isnull(d.data_precision, convert(int,c.length))
  1905.                         +isnull(d.aux, convert(int,
  1906.                         ascii(substring("???AAAFFFCKFOLS",
  1907.                         2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
  1908.             length = isnull(d.length, convert(int,c.length)) +convert(int,
  1909.                         isnull(d.aux,
  1910.                         ascii(substring("AAA<BB<DDDHJSPP",
  1911.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  1912.                         1))-64)),
  1913.             scale = d.numeric_scale +convert(smallint,
  1914.                         isnull(d.aux,
  1915.                         ascii(substring("<<<<<<<<<<<<<<?",
  1916.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  1917.                         1))-60)),
  1918.             radix = d.numeric_radix,
  1919.             nullable = convert(smallint,t.allownulls),
  1920.             remarks = convert(varchar(254),null),    /* Remarks are NULL */
  1921.             ss_data_type = c.type,
  1922.             colid = c.colid
  1923.         FROM
  1924.             syscolumns c,
  1925.             sysobjects o,
  1926.             master.dbo.spt_datatype_info d,
  1927.             systypes t,
  1928.             sysprocedures p
  1929.         WHERE
  1930.             o.id = @procedure_id
  1931.             AND c.id = o.id
  1932.             AND c.usertype = t.usertype
  1933.             AND c.type = d.ss_dtype
  1934.             AND c.name like @column_name
  1935.             AND d.ss_dtype IN (111, 109, 38, 110)    /* Just *N types */
  1936.             AND c.number = @group_num
  1937.         UNION
  1938.         SELECT           /* All other types including user data types */
  1939.             procedure_qualifier = DB_NAME(),
  1940.             procedure_owner = USER_NAME(o.uid),
  1941.             procedure_name = o.name +';'+ ltrim(str(c.number,5)),
  1942.             column_name = c.name,
  1943.             column_type = convert(smallint, 0),
  1944.             data_type = convert(smallint,
  1945.                 /*    Map systypes.type to ODBC type */
  1946.                 /*        SS-Type         "                     1          "*/
  1947.                 /*                        "33 3 3     4 44 5 5 2 5 55666"*/
  1948.                 /*                        "45 7 9        5 78 0 2 2 6 89012"*/
  1949.                         ascii(substring("8;<9<H<<<<<:<=6<5<A<?<@<GC?GB",
  1950.                         t.type%34+1,1))-60),
  1951.             type_name = t.name,
  1952.             precision = isnull(d.data_precision, convert(int,c.length))
  1953.                         +isnull(d.aux, convert(int,
  1954.                         ascii(substring("???AAAFFFCKFOLS",
  1955.                         2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
  1956.             length = isnull(d.length, convert(int,c.length)) +convert(int,
  1957.                         isnull(d.aux,
  1958.                         ascii(substring("AAA<BB<DDDHJSPP",
  1959.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  1960.                         1))-64)),
  1961.             scale = d.numeric_scale +convert(smallint,
  1962.                         isnull(d.aux,
  1963.                         ascii(substring("<<<<<<<<<<<<<<?",
  1964.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  1965.                         1))-60)),
  1966.             radix = d.numeric_radix,
  1967.             nullable = convert(smallint,t.allownulls),
  1968.             remarks = convert(varchar(254),null),    /* Remarks are NULL */
  1969.             ss_data_type = c.type,
  1970.             colid = c.colid
  1971.         FROM
  1972.             syscolumns c,
  1973.             sysobjects o,
  1974.             master.dbo.spt_datatype_info d,
  1975.             systypes t
  1976.         WHERE
  1977.             o.id = @procedure_id
  1978.             AND c.id = o.id
  1979.             AND c.type = d.ss_dtype
  1980.             AND c.usertype *= t.usertype
  1981.             AND c.name like @column_name
  1982.             AND d.ss_dtype NOT IN (111, 109, 38, 110)    /* No *N types */
  1983.             AND c.number = @group_num
  1984.         UNION
  1985.         SELECT           /* return value row*/
  1986.             procedure_qualifier = DB_NAME(),
  1987.             procedure_owner = USER_NAME(o.uid),
  1988.             procedure_name = o.name +';'+ ltrim(str(c.number,5)),
  1989.             column_name = convert(varchar(32),'RETURN_VALUE'),
  1990.             column_type = convert(smallint, 5),
  1991.             data_type = convert(smallint, 4),
  1992.             type_name = convert(varchar(32),'int'),
  1993.             precision = convert(int,10),
  1994.             length = convert(int,4),
  1995.             scale = convert(smallint,0),
  1996.             radix = convert(smallint,10),
  1997.             nullable = convert(smallint,0),
  1998.             remarks = convert(varchar(254),null),    /* Remarks are NULL */
  1999.             ss_data_type = convert(tinyint,56),
  2000.             colid = convert(tinyint,0)
  2001.         FROM
  2002.             syscolumns c,
  2003.             sysobjects o
  2004.         WHERE
  2005.             o.id = @procedure_id
  2006.             AND c.id = o.id
  2007.             AND 'RETURN_VALUE' like @column_name
  2008.         ORDER BY procedure_qualifier, procedure_owner, procedure_name, column_type, colid
  2009.     end
  2010.     else
  2011.     begin
  2012.         /* this block is for the case where there IS pattern
  2013.             matching done on the procedure name */
  2014.         if @procedure_owner is null
  2015.             select @procedure_owner = '%'
  2016.         SELECT    /* INTn, FLOATn, DATETIMEn and MONEYn types */
  2017.             procedure_qualifier = DB_NAME(),
  2018.             procedure_owner = USER_NAME(o.uid),
  2019.             procedure_name = o.name +';'+ ltrim(str(c.number,5)),
  2020.             column_name = c.name,
  2021.             column_type = convert(smallint, 0),
  2022.             data_type = d.data_type+convert(smallint,
  2023.                         isnull(d.aux,
  2024.                         ascii(substring("666AAA@@@CB??GG",
  2025.                         2*(d.ss_dtype%35+1)+2-8/c.length,1))
  2026.                         -60)),
  2027.             type_name = rtrim(substring(d.type_name,
  2028.                         1+isnull(d.aux,
  2029.                         ascii(substring("III<<<MMMI<<A<A",
  2030.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  2031.                         1))-60), 13)),
  2032.             precision = isnull(d.data_precision, convert(int,c.length))
  2033.                         +isnull(d.aux, convert(int,
  2034.                         ascii(substring("???AAAFFFCKFOLS",
  2035.                         2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
  2036.             length = isnull(d.length, convert(int,c.length)) +convert(int,
  2037.                         isnull(d.aux,
  2038.                         ascii(substring("AAA<BB<DDDHJSPP",
  2039.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  2040.                         1))-64)),
  2041.             scale = d.numeric_scale +convert(smallint,
  2042.                         isnull(d.aux,
  2043.                         ascii(substring("<<<<<<<<<<<<<<?",
  2044.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  2045.                         1))-60)),
  2046.             radix = d.numeric_radix,
  2047.             nullable = convert(smallint,t.allownulls),
  2048.             remarks = convert(varchar(254),null),    /* Remarks are NULL */
  2049.             ss_data_type = c.type,
  2050.             colid = c.colid
  2051.         FROM
  2052.             syscolumns c,
  2053.             sysobjects o,
  2054.             master.dbo.spt_datatype_info d,
  2055.             systypes t
  2056.         WHERE
  2057.             o.name like @procedure_name
  2058.             AND user_name(o.uid) like @procedure_owner
  2059.             AND o.id = c.id
  2060.             AND c.usertype = t.usertype
  2061.             AND c.type = d.ss_dtype
  2062.             AND c.name like @column_name
  2063.             AND o.type = 'P'                        /* Just Procedures */
  2064.             AND d.ss_dtype IN (111, 109, 38, 110)    /* Just *N types */
  2065.         UNION
  2066.         SELECT           /* All other types including user data types */
  2067.             procedure_qualifier = DB_NAME(),
  2068.             procedure_owner = USER_NAME(o.uid),
  2069.             procedure_name = o.name +';'+ ltrim(str(c.number,5)),
  2070.             column_name = c.name,
  2071.             column_type = convert(smallint, 0),
  2072.             data_type = convert(smallint,
  2073.                 /*    Map systypes.type to ODBC type */
  2074.                 /*        SS-Type         "                     1          "*/
  2075.                 /*                        "33 3 3     4 44 5 5 2 5 55666"*/
  2076.                 /*                        "45 7 9        5 78 0 2 2 6 89012"*/
  2077.                         ascii(substring("8;<9<H<<<<<:<=6<5<A<?<@<GC?GB",
  2078.                         t.type%34+1,1))-60),
  2079.             type_name = t.name,
  2080.             precision = isnull(d.data_precision, convert(int,c.length))
  2081.                         +isnull(d.aux, convert(int,
  2082.                         ascii(substring("???AAAFFFCKFOLS",
  2083.                         2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
  2084.             length = isnull(d.length, convert(int,c.length)) +convert(int,
  2085.                         isnull(d.aux,
  2086.                         ascii(substring("AAA<BB<DDDHJSPP",
  2087.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  2088.                         1))-64)),
  2089.             scale = d.numeric_scale +convert(smallint,
  2090.                         isnull(d.aux,
  2091.                         ascii(substring("<<<<<<<<<<<<<<?",
  2092.                         2*(d.ss_dtype%35+1)+2-8/c.length,
  2093.                         1))-60)),
  2094.             radix = d.numeric_radix,
  2095.             nullable = convert(smallint,t.allownulls),
  2096.             remarks = convert(varchar(254),null),    /* Remarks are NULL */
  2097.             ss_data_type = c.type,
  2098.             colid = c.colid
  2099.         FROM
  2100.             syscolumns c,
  2101.             sysobjects o,
  2102.             master.dbo.spt_datatype_info d,
  2103.             systypes t
  2104.         WHERE
  2105.             o.name like @procedure_name
  2106.             AND user_name(o.uid) like @procedure_owner
  2107.             AND o.id = c.id
  2108.             AND c.type = d.ss_dtype
  2109.             AND c.usertype *= t.usertype
  2110.             AND o.type = 'P'                            /* Just Procedures */
  2111.             AND c.name like @column_name
  2112.             AND d.ss_dtype NOT IN (111, 109, 38, 110)    /* No *N types */
  2113.         UNION
  2114.         SELECT           /* return value row*/
  2115.             procedure_qualifier = DB_NAME(),
  2116.             procedure_owner = USER_NAME(o.uid),
  2117.             procedure_name = o.name +';'+ ltrim(str(c.number,5)),
  2118.             column_name = convert(varchar(32),'RETURN_VALUE'),
  2119.             column_type = convert(smallint, 5),
  2120.             data_type = convert(smallint, 4),
  2121.             type_name = convert(varchar(32),'int'),
  2122.             precision = convert(int,10),
  2123.             length = convert(int,4),
  2124.             scale = convert(smallint,0),
  2125.             radix = convert(smallint,10),
  2126.             nullable = convert(smallint,0),
  2127.             remarks = convert(varchar(254),null),    /* Remarks are NULL */
  2128.             ss_data_type = convert(tinyint,56),
  2129.             colid = convert(tinyint,0)
  2130.         FROM
  2131.             syscolumns c,
  2132.             sysobjects o
  2133.         WHERE
  2134.             o.name like @procedure_name
  2135.             AND user_name(o.uid) like @procedure_owner
  2136.             AND o.id = c.id
  2137.             AND o.type = 'P'                        /* Just Procedures */
  2138.             AND 'RETURN_VALUE' like @column_name
  2139.         ORDER BY procedure_qualifier, procedure_owner, procedure_name, column_type, colid
  2140.     end
  2141. go
  2142.  
  2143. grant execute on sp_sproc_columns to public
  2144. go
  2145.  
  2146. print "creating sp_table_privileges"
  2147. go
  2148.  
  2149. CREATE PROCEDURE sp_table_privileges (
  2150.             @table_name         varchar(32),
  2151.             @table_owner        varchar(32) = null,
  2152.             @table_qualifier    varchar(32) = null)
  2153. as
  2154.  
  2155.     declare @table_id    int,
  2156.             @owner_id     int,
  2157.             @full_table_name char(70)
  2158.  
  2159.     if @table_qualifier is not null
  2160.     begin
  2161.         if db_name() != @table_qualifier
  2162.         begin    /* If qualifier doesn't match current database */
  2163.             print "Table qualifier must be name of current database"
  2164.             return
  2165.         end
  2166.     end
  2167.     if @table_owner is null
  2168.     begin    /* If unqualified table name */
  2169.         SELECT @full_table_name = @table_name
  2170.     end
  2171.     else
  2172.     begin    /* Qualified table name */
  2173.         SELECT @full_table_name = @table_owner + '.' + @table_name
  2174.     end
  2175.     /*    Get Object ID */
  2176.     SELECT @table_id = object_id(@full_table_name)
  2177.  
  2178.     if @@trancount != 0
  2179.     begin    /* If inside a transaction */
  2180.         raiserror 20001 "catalog procedure sp_table_privileges can not be run in a transaction"
  2181.         return
  2182.     end
  2183.     create table #table_priv1(
  2184.         table_qualifier        varchar(32),
  2185.         table_owner         varchar(32),
  2186.         table_name            varchar(32),
  2187.         grantor             varchar(32),
  2188.         grantee             varchar(32),
  2189.         select_privilege    int,
  2190.         insert_privilege    int,
  2191.         update_privilege    int,
  2192.         delete_privilege    int,
  2193.         is_grantable        varchar(3),
  2194.         uid                 int,
  2195.         gid                 int)
  2196.  
  2197.     insert into #table_priv1
  2198.         select distinct
  2199.             db_name(),
  2200.             user_name(o.uid),
  2201.             o.name,
  2202.             user_name(o.uid),
  2203.             u.name,
  2204.             0,
  2205.             0,
  2206.             0,
  2207.             0,
  2208.             'no',
  2209.             u.uid,
  2210.             u.gid
  2211.         from sysusers u, sysobjects o
  2212.         where o.id = @table_id and u.uid != u.gid
  2213.            and sysstat & 7 in (1,2,3)    /* only valid for system tables,
  2214.                                            ** user tables, and views. */
  2215.  
  2216.     /*
  2217.     ** now add row for table owner
  2218.     */
  2219.     if exists (
  2220.         select *
  2221.             from #table_priv1
  2222.             where grantor = grantee)
  2223.     begin
  2224.         update #table_priv1
  2225.         set
  2226.             select_privilege = 1,
  2227.             update_privilege = 1,
  2228.             insert_privilege = 1,
  2229.             delete_privilege = 1,
  2230.             is_grantable = 'yes'
  2231.         where grantor = grantee
  2232.     end
  2233.     else
  2234.     begin
  2235.         insert into #table_priv1
  2236.             select    db_name(),
  2237.                 user_name(o.uid),
  2238.                 o.name,
  2239.                 user_name(o.uid),
  2240.                 user_name(o.uid),
  2241.                 1,
  2242.                 1,
  2243.                 1,
  2244.                 1,
  2245.                 'yes',
  2246.                 o.uid,
  2247.                 u.gid
  2248.             from sysobjects o, sysusers u
  2249.             where o.id = @table_id and u.uid = o.uid
  2250.             and sysstat & 7 in (1,2,3)    /* only valid for system tables,
  2251.                                            ** user tables, and views. */
  2252.  
  2253.     end
  2254.  
  2255.     update #table_priv1
  2256.     set select_privilege = 1
  2257.     where
  2258.         exists (
  2259.             select * from sysprotects
  2260.             where
  2261.                 id = @table_id
  2262.                 and (#table_priv1.uid = uid
  2263.                     or #table_priv1.gid = uid
  2264.                     or uid = 0)
  2265.                 and protecttype = 205
  2266.                 and action = 193)
  2267.         and not exists (
  2268.             select * from sysprotects
  2269.             where
  2270.                 id = @table_id
  2271.                 and (#table_priv1.uid = uid
  2272.                     or #table_priv1.gid = uid
  2273.                     or uid = 0)
  2274.                 and protecttype = 206
  2275.                 and action = 193)
  2276.  
  2277.     update #table_priv1
  2278.     set insert_privilege = 1
  2279.     where
  2280.         exists (
  2281.             select * from sysprotects
  2282.             where
  2283.                 id = @table_id
  2284.                 and (#table_priv1.uid = uid
  2285.                     or #table_priv1.gid = uid
  2286.                     or uid = 0)
  2287.                 and protecttype = 205
  2288.                 and action = 195)
  2289.         and not exists (
  2290.             select * from sysprotects
  2291.             where
  2292.                 id = @table_id
  2293.                 and (#table_priv1.uid = uid
  2294.                     or #table_priv1.gid = uid
  2295.                     or uid = 0)
  2296.                 and protecttype = 206
  2297.                 and action = 195)
  2298.  
  2299.     update #table_priv1
  2300.     set delete_privilege = 1
  2301.     where
  2302.         exists (
  2303.             select * from sysprotects
  2304.             where
  2305.                 id = @table_id
  2306.                 and (#table_priv1.uid = uid
  2307.                     or #table_priv1.gid = uid
  2308.                     or uid = 0)
  2309.                 and protecttype = 205
  2310.                 and action = 196)
  2311.         and not exists (select * from sysprotects
  2312.             where
  2313.                 id = @table_id
  2314.                 and (#table_priv1.uid = uid
  2315.                     or #table_priv1.gid = uid
  2316.                     or uid = 0)
  2317.                 and protecttype = 206
  2318.                 and action = 196)
  2319.  
  2320.     update #table_priv1
  2321.     set update_privilege = 1
  2322.     where
  2323.         exists (
  2324.             select * from sysprotects
  2325.             where
  2326.                 id = @table_id
  2327.                 and (#table_priv1.uid = uid
  2328.                     or #table_priv1.gid = uid
  2329.                     or uid = 0)
  2330.                 and protecttype = 205
  2331.                 and action = 197)
  2332.         and not exists (
  2333.             select * from sysprotects
  2334.             where
  2335.                 id = @table_id
  2336.                 and (#table_priv1.uid = uid
  2337.                     or #table_priv1.gid = uid
  2338.                     or uid = 0)
  2339.                 and protecttype = 206
  2340.                 and action = 197)
  2341.  
  2342.     create table #table_priv2(
  2343.         table_qualifier varchar(32),
  2344.         table_owner     varchar(32),
  2345.         table_name        varchar(32),
  2346.         grantor         varchar(32),
  2347.         grantee         varchar(32),
  2348.         privilege        varchar(32),
  2349.         is_grantable    varchar(3))
  2350.  
  2351.     insert into #table_priv2
  2352.         select
  2353.             table_qualifier,
  2354.             table_owner,
  2355.             table_name,
  2356.             grantor,
  2357.             grantee,
  2358.             'SELECT',
  2359.             is_grantable
  2360.         from #table_priv1
  2361.         where select_privilege = 1
  2362.  
  2363.  
  2364.     insert into #table_priv2
  2365.         select
  2366.             table_qualifier,
  2367.             table_owner,
  2368.             table_name,
  2369.             grantor,
  2370.             grantee,
  2371.             'INSERT',
  2372.             is_grantable
  2373.         from #table_priv1
  2374.         where insert_privilege = 1
  2375.  
  2376.  
  2377.     insert into #table_priv2
  2378.         select
  2379.             table_qualifier,
  2380.             table_owner,
  2381.             table_name,
  2382.             grantor,
  2383.             grantee,
  2384.             'DELETE',
  2385.             is_grantable
  2386.         from #table_priv1
  2387.         where delete_privilege = 1
  2388.  
  2389.  
  2390.     insert into #table_priv2
  2391.         select
  2392.             table_qualifier,
  2393.             table_owner,
  2394.             table_name,
  2395.             grantor,
  2396.             grantee,
  2397.             'UPDATE',
  2398.             is_grantable
  2399.         from #table_priv1
  2400.         where update_privilege = 1
  2401.  
  2402.  
  2403.     select * from #table_priv2
  2404.     order by privilege
  2405. go
  2406.  
  2407. grant execute on sp_table_privileges to public
  2408. go
  2409.  
  2410. dump tran master with truncate_only
  2411. go
  2412.  
  2413. print "creating sp_column_privileges"
  2414. go
  2415.  
  2416.  
  2417. CREATE PROCEDURE sp_column_privileges (
  2418.             @table_name         varchar(32),
  2419.             @table_owner        varchar(32) = null,
  2420.             @table_qualifier    varchar(32) = null,
  2421.             @column_name        varchar(32) = null)
  2422. as
  2423.  
  2424.     declare @table_id    int,
  2425.     @owner_id    int
  2426.     DECLARE @full_table_name    char(70)
  2427.     declare @low int                    /* range of userids to check */
  2428.     declare @high int
  2429.     declare @objid int                  /* id of @name if object */
  2430.     declare @owner_name varchar(32)
  2431.  
  2432.     select @low = 0, @high = 32767
  2433.  
  2434.     if @column_name is null /*    If column name not supplied, match all */
  2435.         select @column_name = '%'
  2436.  
  2437.     if @table_qualifier is not null
  2438.     begin
  2439.         if db_name() != @table_qualifier
  2440.         begin    /* If qualifier doesn't match current database */
  2441.             print "Table qualifier must be name of current database"
  2442.             return
  2443.         end
  2444.     end
  2445.     if @table_owner is null
  2446.     begin    /* If unqualified table name */
  2447.         SELECT @full_table_name = @table_name
  2448.     end
  2449.     else
  2450.     begin    /* Qualified table name */
  2451.         SELECT @full_table_name = @table_owner + '.' + @table_name
  2452.     end
  2453.     /*    Get Object ID */
  2454.     select @table_id = object_id(@full_table_name)
  2455.  
  2456.     if @@trancount != 0
  2457.     begin    /* If inside a transaction */
  2458.         raiserror 20001 "catalog procedure sp_column_privileges can not be run in a transaction"
  2459.         return
  2460.     end
  2461.  
  2462.     /*
  2463.     ** We need to create a table which will contain a row for every row to
  2464.     ** be returned to the client.
  2465.     */
  2466.  
  2467.     create table #column_priv1(
  2468.         table_qualifier            varchar(32),
  2469.         table_owner             varchar(32),
  2470.         table_name                varchar(32),
  2471.         column_name             varchar(32),
  2472.         grantor                 varchar(32),
  2473.         grantee                 varchar(32),
  2474.         select_privilege        int,
  2475.         select_grantable        int,
  2476.         insert_privilege        int,
  2477.         insert_grantable        int,
  2478.         update_privilege        int,
  2479.         update_grantable        int,
  2480.         delete_privilege        int,
  2481.         delete_grantable        int,
  2482.         references_privilege    int null,
  2483.         references_grantable    int null,
  2484.         uid                     int,
  2485.         gid                     int,
  2486.         is_grantable            varchar(3))
  2487.  
  2488. /*
  2489. ** insert a row for the table owner (who has all permissions)
  2490. */
  2491.     select @owner_name = (
  2492.         select user_name(uid)
  2493.         from sysobjects
  2494.         where id = @table_id)
  2495.  
  2496.     insert into #column_priv1
  2497.         select
  2498.             db_name(),
  2499.             @owner_name,
  2500.             @table_name,
  2501.             name,
  2502.             @owner_name,
  2503.             @owner_name,
  2504.             1,
  2505.             1,
  2506.             1,
  2507.             1,
  2508.             1,
  2509.             1,
  2510.             1,
  2511.             1,
  2512.             null,
  2513.             null,
  2514.             user_id(@owner_name),
  2515.             0,
  2516.             'yes'
  2517.         from syscolumns
  2518.         where id = @table_id
  2519.  
  2520. /*
  2521. ** now stick a row in the table for every user in the database
  2522. ** we will need to weed out those who have no permissions later
  2523. ** (and yes this is a cartesion product: the uid field in sysprotects
  2524. ** can also have a group id, in which case we need to extend those
  2525. ** privileges to all group members).
  2526. */
  2527.  
  2528.     insert into #column_priv1
  2529.         select distinct
  2530.             db_name(),
  2531.             user_name(o.uid),
  2532.             @table_name,
  2533.             c.name,
  2534.             user_name(o.uid),
  2535.             u.name,
  2536.             0,
  2537.             0,
  2538.             0,
  2539.             0,
  2540.             0,
  2541.             0,
  2542.             0,
  2543.             0,
  2544.             null,
  2545.             null,
  2546.             u.uid,
  2547.             u.gid,
  2548.             'no'
  2549.         from sysusers u, syscolumns c, sysobjects o
  2550.         where o.id = @table_id
  2551.             and c.id = o.id
  2552.             and u.gid != u.uid
  2553.             and u.name != @owner_name
  2554.  
  2555.     /*
  2556.     ** we need to create another temporary table to contain all the various
  2557.     ** protection information for the table in question
  2558.     */
  2559.     create table #protects (
  2560.                 uid         smallint,
  2561.                 action        tinyint,
  2562.                 protecttype tinyint,
  2563.                 name        varchar(32))
  2564.  
  2565.     insert into #protects
  2566.         select
  2567.             p.uid,
  2568.             p.action,
  2569.             p.protecttype,
  2570.             isnull(col_name(id, c.number), "All")
  2571.             from
  2572.                 sysprotects p,
  2573.                 master.dbo.spt_values c,
  2574.                 master.dbo.spt_values a,
  2575.                 master.dbo.spt_values b
  2576.             where
  2577.                 convert(tinyint, substring(isnull(p.columns, 0x1), c.low, 1))
  2578.                     & c.high != 0
  2579.                     and c.number <= (
  2580.                         select count(*)
  2581.                         from syscolumns
  2582.                         where id = @table_id)
  2583.                 and a.type = "T"
  2584.                 and a.number = p.action
  2585.                 and b.type = "T"
  2586.                 and b.number = p.protecttype
  2587.                 and p.id = @table_id
  2588.                 and p.uid between @low and @high
  2589.  
  2590.  
  2591.     update #column_priv1
  2592.     set select_privilege = 1
  2593.     where
  2594.         exists (
  2595.             select * from #protects
  2596.             where
  2597.                 protecttype = 205
  2598.                 and action = 193
  2599.                 and (name = #column_priv1.column_name
  2600.                     or name = 'All')
  2601.                 and (uid = 0
  2602.                     or uid = #column_priv1.gid
  2603.                     or uid = #column_priv1.uid))
  2604.         and not exists (
  2605.             select * from #protects
  2606.             where
  2607.                 protecttype = 206
  2608.                 and action = 193
  2609.                 and (name = #column_priv1.column_name
  2610.                     or name = 'All')
  2611.                 and ( uid = 0
  2612.                     or uid = #column_priv1.gid
  2613.                     or uid = #column_priv1.uid))
  2614.  
  2615.     update #column_priv1
  2616.     set insert_privilege = 1
  2617.     where
  2618.         exists (
  2619.             select * from #protects
  2620.             where
  2621.                 protecttype = 205
  2622.                 and action = 195
  2623.                 and (name = #column_priv1.column_name
  2624.                     or name = 'All')
  2625.                 and (uid = 0
  2626.                     or uid = #column_priv1.gid
  2627.                     or uid = #column_priv1.uid))
  2628.         and not exists (
  2629.             select * from #protects
  2630.             where
  2631.                 protecttype = 206
  2632.                 and action = 195
  2633.                 and (name = #column_priv1.column_name
  2634.                     or name = 'All')
  2635.                 and (uid = 0
  2636.                     or uid = #column_priv1.gid
  2637.                     or uid = #column_priv1.uid))
  2638.  
  2639.     update #column_priv1
  2640.     set insert_privilege = 1
  2641.     where
  2642.         exists (
  2643.             select * from #protects
  2644.             where
  2645.                 protecttype = 205
  2646.                 and action = 196
  2647.                 and (name = #column_priv1.column_name
  2648.                     or name = 'All')
  2649.                 and (uid = 0
  2650.                     or uid = #column_priv1.gid
  2651.                     or uid = #column_priv1.uid))
  2652.         and not exists (
  2653.             select * from #protects
  2654.             where
  2655.                 protecttype = 206
  2656.                 and action = 196
  2657.                 and (name = #column_priv1.column_name
  2658.                     or name = 'All')
  2659.                 and (uid = 0
  2660.                     or uid = #column_priv1.gid
  2661.                     or uid = #column_priv1.uid))
  2662.  
  2663.  
  2664.     update #column_priv1
  2665.     set update_privilege = 1
  2666.         where
  2667.             exists (
  2668.                 select * from #protects
  2669.                 where protecttype = 205
  2670.                 and action = 197
  2671.                 and (name = #column_priv1.column_name
  2672.                     or name = 'All')
  2673.                 and (uid = 0
  2674.                     or uid = #column_priv1.gid
  2675.                     or uid = #column_priv1.uid))
  2676.             and not exists (
  2677.                 select * from #protects
  2678.                     where protecttype = 206
  2679.                     and action = 197
  2680.                     and (name = #column_priv1.column_name
  2681.                         or name = 'All')
  2682.                     and (uid = 0
  2683.                         or uid = #column_priv1.gid
  2684.                         or uid = #column_priv1.uid))
  2685.  
  2686.     create table #column_priv2(
  2687.         table_qualifier varchar(32),
  2688.         table_owner     varchar(32),
  2689.         table_name        varchar(32),
  2690.         column_name     varchar(32),
  2691.         grantor         varchar(32),
  2692.         grantee         varchar(32),
  2693.         privilege        varchar(32),
  2694.         is_grantable    varchar(3))
  2695.  
  2696.     insert into #column_priv2
  2697.         select
  2698.             table_qualifier,
  2699.             table_owner,
  2700.             table_name,
  2701.             column_name,
  2702.             grantor,
  2703.             grantee,
  2704.             'SELECT',
  2705.             is_grantable
  2706.         from #column_priv1
  2707.         where select_privilege = 1
  2708.  
  2709.     insert into #column_priv2
  2710.         select
  2711.             table_qualifier,
  2712.             table_owner,
  2713.             table_name,
  2714.             column_name,
  2715.             grantor,
  2716.             grantee,
  2717.             'INSERT',
  2718.             is_grantable
  2719.         from #column_priv1
  2720.         where insert_privilege = 1
  2721.  
  2722.     insert into #column_priv2
  2723.         select
  2724.             table_qualifier,
  2725.             table_owner,
  2726.             table_name,
  2727.             column_name,
  2728.             grantor,
  2729.             grantee,
  2730.             'UPDATE',
  2731.             is_grantable
  2732.         from #column_priv1
  2733.         where update_privilege = 1
  2734.  
  2735.     select * from #column_priv2
  2736.     where column_name like @column_name
  2737.     order by column_name, privilege
  2738. go
  2739.  
  2740. grant execute on sp_column_privileges to public
  2741. go
  2742.  
  2743. dump tran master with truncate_only
  2744. go
  2745.  
  2746.  
  2747. print "creating sp_server_info"
  2748. go
  2749.  
  2750. create proc sp_server_info (
  2751.             @attribute_id  int = null)
  2752. as
  2753.     if @attribute_id is not null
  2754.         select *
  2755.         from master.dbo.spt_server_info
  2756.         where attribute_id = @attribute_id
  2757.     else
  2758.         select *
  2759.         from master.dbo.spt_server_info
  2760.         order by attribute_id
  2761. go
  2762.  
  2763. grant execute on sp_server_info to public
  2764. go
  2765.  
  2766. print "creating sp_datatype_info"
  2767. go
  2768.  
  2769. /* the messiness of 'data_type' was to get around the problem of
  2770. returning the correct lengths for user defined types.  the join
  2771. on the type name ensures all user defined types are returned, but
  2772. this puts a null in the data_type column.  by forcing an embedded
  2773. select and correlating it with the current row in systypes, we get
  2774. the correct data_type mapping even for user defined types  (kwg) */
  2775.  
  2776. create proc sp_datatype_info
  2777.     (@data_type int = 0)
  2778. as
  2779.     if @data_type = 0
  2780.                select    /* Real SQL Server data types */
  2781.             type_name = t.name,
  2782.             d.data_type,
  2783.             precision = isnull(d.data_precision, convert(int,t.length)),
  2784.             d.literal_prefix,
  2785.             d.literal_suffix,
  2786.             e.create_params,
  2787.             d.nullable,
  2788.             d.case_sensitive,
  2789.             d.searchable,
  2790.             d.unsigned_attribute,
  2791.             d.money,
  2792.             d.auto_increment,
  2793.             d.local_type_name,
  2794.             minimum_scale = d.numeric_scale,
  2795.             maximum_scale = d.numeric_scale
  2796.         from master.dbo.spt_datatype_info d, master.dbo.spt_datatype_info_ext e, systypes t
  2797.         where
  2798.             d.ss_dtype = t.type
  2799.             and t.usertype *= e.user_type
  2800.             and t.usertype not in (80,18)        /* No SYSNAME or TIMESTAMP */
  2801.             and t.usertype < 100                /* No user defined types */
  2802.             and t.type not in (111,109,38,110)    /* get rid of nullable types */
  2803.             and t.name != 'nchar'                /* get rid of 4.9.1 type */
  2804.             and t.name != 'nvarchar'            /* get rid of 4.9.1 type */
  2805.         UNION
  2806.         select    /* SQL Server SYSNAME, TIMESTAMP and user data types */
  2807.             type_name = t.name,
  2808.             d.data_type,
  2809.             precision = isnull(d.data_precision, convert(int,t.length)),
  2810.             d.literal_prefix,
  2811.             d.literal_suffix,
  2812.             e.create_params,
  2813.             d.nullable,
  2814.             d.case_sensitive,
  2815.             d.searchable,
  2816.             d.unsigned_attribute,
  2817.             d.money,
  2818.             d.auto_increment,
  2819.             t.name,
  2820.             minimum_scale = d.numeric_scale,
  2821.             maximum_scale = d.numeric_scale
  2822.         from master.dbo.spt_datatype_info d, master.dbo.spt_datatype_info_ext e, systypes t
  2823.         where
  2824.             d.ss_dtype = t.type
  2825.             and t.usertype *= e.user_type
  2826.             and (t.usertype in (80,18)            /* SYSNAME or TIMESTAMP */
  2827.                 or t.usertype >= 100)            /* User defined types */
  2828.             and t.type not in (111,109,38,110)    /* get rid of nullable types */
  2829.         order by d.data_type, type_name
  2830.  
  2831.     else
  2832.         select    /* Real SQL Server data types */
  2833.             type_name = t.name,
  2834.             d.data_type,
  2835.             precision = isnull(d.data_precision, convert(int,t.length)),
  2836.             d.literal_prefix,
  2837.             d.literal_suffix,
  2838.             e.create_params,
  2839.             d.nullable,
  2840.             d.case_sensitive,
  2841.             d.searchable,
  2842.             d.unsigned_attribute,
  2843.             d.money,
  2844.             d.auto_increment,
  2845.             d.local_type_name,
  2846.             minimum_scale = d.numeric_scale,
  2847.             maximum_scale = d.numeric_scale
  2848.         from master.dbo.spt_datatype_info d, master.dbo.spt_datatype_info_ext e, systypes t
  2849.         where
  2850.             data_type = @data_type
  2851.             and d.ss_dtype = t.type
  2852.             and t.usertype *= e.user_type
  2853.             and t.usertype not in (80,18)        /* No SYSNAME or TIMESTAMP */
  2854.             and t.usertype < 100                /* No user defined types */
  2855.             and t.type not in (111,109,38,110)    /* get rid of nullable types */
  2856.             and t.name != 'nchar'                /* get rid of 4.9.1 type */
  2857.             and t.name != 'nvarchar'            /* get rid of 4.9.1 type */
  2858.         UNION
  2859.         select    /* SQL Server SYSNAME, TIMESTAMP and user data types */
  2860.             type_name = t.name,
  2861.             d.data_type,
  2862.             precision = isnull(d.data_precision, convert(int,t.length)),
  2863.             d.literal_prefix,
  2864.             d.literal_suffix,
  2865.             e.create_params,
  2866.             d.nullable,
  2867.             d.case_sensitive,
  2868.             d.searchable,
  2869.             d.unsigned_attribute,
  2870.             d.money,
  2871.             d.auto_increment,
  2872.             t.name,
  2873.             minimum_scale = d.numeric_scale,
  2874.             maximum_scale = d.numeric_scale
  2875.         from master.dbo.spt_datatype_info d, master.dbo.spt_datatype_info_ext e, systypes t
  2876.         where
  2877.             data_type = @data_type
  2878.             and d.ss_dtype = t.type
  2879.             and t.usertype *= e.user_type
  2880.             and (t.usertype in (80,18)            /* SYSNAME or TIMESTAMP */
  2881.                 or t.usertype >= 100)            /* User defined types */
  2882.             and t.type not in (111,109,38,110)    /* get rid of nullable types */
  2883.         order by type_name
  2884.  
  2885. go
  2886.  
  2887. grant execute on sp_datatype_info to public
  2888. go
  2889.  
  2890. dump tran master with truncate_only
  2891. go
  2892.  
  2893. print "creating sp_special_columns"
  2894. go
  2895.  
  2896. dump tran master with truncate_only
  2897. go
  2898.  
  2899. CREATE PROCEDURE sp_special_columns (
  2900.                  @table_name        varchar(32),
  2901.                  @table_owner        varchar(32) = null,
  2902.                  @table_qualifier    varchar(32) = null,
  2903.                  @col_type            char(1) = 'R',
  2904.                  @scope                char(1) = 'T',
  2905.                  @nullable            char(1) = 'U')
  2906. AS
  2907.     DECLARE @indid                int
  2908.     DECLARE @table_id            int
  2909.     DECLARE @full_table_name    char(70)
  2910.     DECLARE @msg                char(70)
  2911.     DECLARE @scopeout            smallint
  2912.  
  2913.     if @col_type not in ('R','V')
  2914.        begin
  2915.           print "Invalid value - please enter either 'R' or 'V' for col_type."
  2916.           return
  2917.        end
  2918.  
  2919.     if @scope = 'C'
  2920.         select @scopeout = 0
  2921.     else if @scope = 'T'
  2922.         select @scopeout = 1
  2923.     else
  2924.        begin
  2925.           print "Invalid value - please enter either 'C' or 'T' for scope."
  2926.           return
  2927.        end
  2928.  
  2929.     if @nullable not in ('U','O')
  2930.        begin
  2931.           print "Invalid value - please enter either 'U' or 'O' for nullable."
  2932.           return
  2933.        end
  2934.  
  2935.     if @table_qualifier is not null
  2936.        begin
  2937.           if db_name() != @table_qualifier
  2938.               begin    /* If qualifier doesn't match current database */
  2939.                 print "Table qualifier must be name of current database"
  2940.                 return
  2941.               end
  2942.        end
  2943.     if @table_owner is null
  2944.        begin    /* If unqualified table name */
  2945.           SELECT @full_table_name = @table_name
  2946.        end
  2947.     else
  2948.        begin    /* Qualified table name */
  2949.           SELECT @full_table_name = @table_owner + '.' + @table_name
  2950.        end
  2951.     /*    Get Object ID */
  2952.     SELECT @table_id = object_id(@full_table_name)
  2953.  
  2954.     if @col_type = 'V'
  2955.     BEGIN /* if ROWVER, just run that query */
  2956.         SELECT
  2957.             scope = convert(smallint,NULL),
  2958.             column_name = c.name,
  2959.             data_type = d.data_type+convert(smallint,
  2960.                             isnull(d.aux,
  2961.                             ascii(substring("666AAA@@@CB??GG",
  2962.                             2*(d.ss_dtype%35+1)+2-8/c.length,1))
  2963.                             -60)),
  2964.             type_name = t.name,
  2965.             precision = isnull(d.data_precision, convert(int,c.length))
  2966.                             +isnull(d.aux, convert(int,
  2967.                             ascii(substring("???AAAFFFCKFOLS",
  2968.                             2*(d.ss_dtype%35+1)+2-8/c.length,1))-60)),
  2969.             length = isnull(d.length, convert(int,c.length)) +convert(int,
  2970.                             isnull(d.aux,
  2971.                             ascii(substring("AAA<BB<DDDHJSPP",
  2972.                             2*(d.ss_dtype%35+1)+2-8/c.length,
  2973.                             1))-64)),
  2974.             scale = d.numeric_scale +convert(smallint,
  2975.                             isnull(d.aux,
  2976.                             ascii(substring("<<<<<<<<<<<<<<?",
  2977.                             2*(d.ss_dtype%35+1)+2-8/c.length,
  2978.                             1))-60)),
  2979.             pseudo_column = convert(smallint,1)
  2980.         FROM
  2981.             systypes t, syscolumns c, master.dbo.spt_datatype_info d
  2982.         WHERE
  2983.             c.id = @table_id
  2984.             AND c.type = d.ss_dtype
  2985.             AND c.usertype = 80 /*    TIMESTAMP */
  2986.             AND t.usertype = 80 /*    TIMESTAMP */
  2987.         RETURN
  2988.     END
  2989.  
  2990.     /* ROWID, now find the id of the 'best' index for this table */
  2991.  
  2992.     IF @nullable = 'O'    /* Don't include any indexes that contain
  2993.                            nullable columns. */
  2994.  
  2995.             SELECT @indid = MIN(indid)
  2996.                 FROM sysindexes i,syscolumns c,syscolumns c2
  2997.                 WHERE
  2998.                     i.status&2 = 2        /*    If Unique Index */
  2999.                      AND c.id = i.id
  3000.                      AND c2.id = c.id
  3001.                      AND c2.colid < i.keycnt + (i.status&16)/16
  3002.                     AND i.id = @table_id
  3003.                     AND indid > 0        /*    Eliminate Table Row */
  3004.                     AND c.name = index_col(@table_name,i.indid,c2.colid)
  3005.                     GROUP BY indid HAVING SUM(c.status&8) = 0
  3006.  
  3007.     ELSE    /* Include indexes that are partially nullable. */
  3008.  
  3009.         SELECT @indid = MIN(indid)
  3010.             FROM sysindexes i
  3011.             WHERE
  3012.                 status&2 = 2        /*    If Unique Index */
  3013.                 AND id = @table_id
  3014.                 AND indid > 0        /*    Eliminate Table Row */
  3015.  
  3016.     SELECT
  3017.         scope = @scopeout,
  3018.         column_name = INDEX_COL(@full_table_name,indid,c.colid),
  3019.         data_type = d.data_type+convert(smallint,
  3020.                         isnull(d.aux,
  3021.                         ascii(substring("666AAA@@@CB??GG",
  3022.                         2*(d.ss_dtype%35+1)+2-8/c2.length,1))
  3023.                         -60)),
  3024.         type_name = rtrim(substring(d.type_name,
  3025.                         1+isnull(d.aux,
  3026.                         ascii(substring("III<<<MMMI<<A<A",
  3027.                         2*(d.ss_dtype%35+1)+2-8/c2.length,
  3028.                         1))-60), 13)),
  3029.         precision = isnull(d.data_precision, convert(int,c2.length))
  3030.                         +isnull(d.aux, convert(int,
  3031.                         ascii(substring("???AAAFFFCKFOLS",
  3032.                         2*(d.ss_dtype%35+1)+2-8/c2.length,1))-60)),
  3033.         length = isnull(d.length, convert(int,c2.length)) +convert(int,
  3034.                         isnull(d.aux,
  3035.                         ascii(substring("AAA<BB<DDDHJSPP",
  3036.                         2*(d.ss_dtype%35+1)+2-8/c2.length,
  3037.                         1))-64)),
  3038.         scale = d.numeric_scale +convert(smallint,
  3039.                         isnull(d.aux,
  3040.                         ascii(substring("<<<<<<<<<<<<<<?",
  3041.                         2*(d.ss_dtype%35+1)+2-8/c2.length,
  3042.                         1))-60)),
  3043.         pseudo_column = convert(smallint,1)
  3044.     FROM
  3045.         sysindexes x,
  3046.         syscolumns c,
  3047.         master.dbo.spt_datatype_info d,
  3048.         systypes t,
  3049.         syscolumns c2    /* Self-join to generate list of index columns and */
  3050.                         /* to extract datatype names */
  3051.     WHERE
  3052.         x.id = @table_id
  3053.         AND c2.name = INDEX_COL(@full_table_name,@indid,c.colid)
  3054.         AND c2.id =x.id
  3055.         AND c.id = x.id
  3056.         AND c.colid < keycnt+(x.status&16)/16
  3057.         AND x.indid = @indid
  3058.         AND c2.type = d.ss_dtype
  3059.         AND c2.usertype *= t.usertype
  3060.  
  3061. go
  3062.  
  3063. grant execute on sp_special_columns to public
  3064. go
  3065.  
  3066. print "creating sp_databases"
  3067. go
  3068.  
  3069. create proc sp_databases
  3070. as
  3071.     /* Use temporary table to sum up database size w/o using group by */
  3072.     create table #databases (
  3073.                   database_name varchar(32),
  3074.                   size int)
  3075.  
  3076.     /* Insert row for each database */
  3077.     insert into #databases
  3078.         select
  3079.             name,
  3080.             (select sum(size) from master.dbo.sysusages
  3081.                 where dbid = d.dbid)
  3082.         from master.dbo.sysdatabases d
  3083.  
  3084.     select
  3085.          database_name,
  3086.          database_size = size*2,    /* Convert from 2048 byte pages to K */
  3087.          remarks = convert(varchar(254),null)    /* Remarks are NULL */
  3088.     from #databases
  3089.     order by database_name
  3090. go
  3091.  
  3092. grant execute on sp_databases to public
  3093. go
  3094.  
  3095. dump tran master with truncate_only
  3096. go
  3097.  
  3098. /*******************************************************************************/
  3099. /* This portion returns everything back to normal                   */
  3100. /*******************************************************************************/
  3101. use master
  3102. go
  3103.  
  3104. if exists (select * from sysobjects
  3105.             where name = 'sp_configure' and sysstat & 7 = 4)
  3106. begin
  3107.     execute sp_configure 'update',0
  3108. end
  3109. reconfigure with override
  3110. go
  3111.  
  3112. checkpoint
  3113. go
  3114.