DatabaseProcApplicationCreatedLinks
sybsystemprocssp_stored_procedures  31 Aug 14Defects Dependencies

1     
2     /* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
3     
4     /*
5     ** Messages for "sp_stored_procedures"	18041
6     **
7     ** 18041, "Stored Procedure qualifier must be name of current database."
8     **
9     */
10    create procedure sp_stored_procedures
11        @sp_name varchar(261) = null, /* stored procedure name */
12        @sp_owner varchar(257) = null, /* stored procedure owner */
13        @sp_qualifier varchar(257) = null /* stored procedure qualifier; 
14    					** For the SQL Server, the only valid
15    					** values are NULL or the current 
16    					** database name
17    					*/
18    as
19    
20        declare @issa int
21    
22        if @@trancount = 0
23        begin
24            set chained off
25        end
26    
27        set transaction isolation level 1
28    
29        /* If qualifier is specified */
30        if @sp_qualifier is not null
31        begin
32            /* If qualifier doesn't match current database */
33            if db_name() != @sp_qualifier
34            begin
35                /* If qualifier is not specified */
36                if @sp_qualifier = ''
37                begin
38                    /* in this case, we need to return an empty 
39                    ** result set because the user has requested a 
40                    ** database with an empty name 
41                    */
42                    select @sp_name = ''
43                    select @sp_owner = ''
44                end
45    
46                /* qualifier is specified and does not match current database */
47                else
48                begin
49                    /* 
50                    ** 18041, "Stored Procedure qualifer must be name of
51                    ** current database"
52                    */
53                    raiserror 18041
54                    return (1)
55                end
56            end
57        end
58    
59        /* If procedure name not supplied, match all */
60        if @sp_name is null
61        begin
62            select @sp_name = '%'
63        end
64        else
65        begin
66            /* If owner name is not supplied, but procedure name is */
67            if (@sp_owner is null) and (charindex('%', @sp_name) = 0)
68            begin
69                /* If procedure exists and is owned by the current user */
70                if exists (select *
71                        from sysobjects
72                        where uid = user_id()
73                            and name = @sp_name
74                            and type = 'P') /* Object type of Procedure */
75                begin
76                    /* Set owner name to current user */
77                    select @sp_owner = user_name()
78                end
79            end
80        end
81    
82        /* If procedure owner not supplied, match all */
83        if @sp_owner is null
84            select @sp_owner = '%'
85    
86        if (suser_id() = 1 or charindex('sa_role', show_role()) > 0)
87            select @issa = 1
88        else
89            select @issa = 0
90    
91        /* 
92        ** Retrieve the stored procedures and associated info on them
93        */
94        select procedure_qualifier = db_name(),
95            procedure_owner = user_name(o.uid),
96            procedure_name = o.name + ';' + ltrim(str(p.number, 5)),
97            num_input_params = - 1, /* Constant since value unknown */
98            num_output_params = - 1, /* Constant since value unknown */
99            num_result_sets = - 1, /* Constant since value unknown */
100           remarks = null /* Remarks are NULL */
101       from sysobjects o, sysprocedures p, sysusers u
102       where o.name like @sp_name
103           and p.sequence = 0
104           and user_name(o.uid) like @sp_owner
105           and o.type = 'P' /* Object type of Procedure */
106           and p.id = o.id
107           and u.uid = user_id() /* constrain sysusers uid for use in 
108           ** subquery 
109           */
110   
111           and (@issa = 1 /* User is the System Administrator */
112               or o.uid = user_id() /* User created the object */
113               /* here's the magic..select the highest 
114               ** precedence of permissions in the 
115               ** order (user,group,public)  
116               */
117   
118               /*
119               ** The value of protecttype is
120               **
121               **		0  for grant with grant
122               **		1  for grant and,
123               **		2  for revoke
124               **
125               ** As protecttype is of type tinyint, protecttype/2 is
126               ** integer division and will yield 0 for both types of
127               ** grants and will yield 1 for revoke, i.e., when
128               ** the value of protecttype is 2.  The XOR (^) operation
129               ** will reverse the bits and thus (protecttype/2)^1 will
130               ** yield a value of 1 for grants and will yield a
131               ** value of zero for revoke.
132               **
133               ** For groups, uid = gid. We shall use this to our advantage.
134               ** 	
135               ** If there are several entries in the sysprotects table
136               ** with the same Object ID, then the following expression
137               ** will prefer an individual uid entry over a group entry
138               **
139               ** For example, let us say there are two users u1 and u2
140               ** with uids 4 and 5 respectiveley and both u1 and u2
141               ** belong to a group g12 whose uid is 16390.  procedure p1
142               ** is owned by user u0 and user u0 performs the following
143               ** actions:
144               **
145               **		grant exec on p1 to g12
146               **		revoke grant on p1 from u1
147               **
148               ** There will be two entries in sysprotects for the object
149               ** p1, one for the group g12 where protecttype = grant (1)
150               ** and one for u1 where protecttype = revoke (2).
151               **
152               ** For the group g12, the following expression will
153               ** evaluate to:
154               **
155               **		((abs(16390-16390)*2) + ((1/2)^1))
156               **		= ((0) + (0)^1) = 0 + 1 = 1
157               **
158               ** For the user entry u1, it will evaluate to:
159               **
160               **		((abs(4-16390)*2) + ((2/2)^1))
161               **		= ((abs(-16386)*2 + (1)^1)
162               **		= 16386*2 + 0 = 32772 
163               **
164               ** As the expression evaluates to a bigger number for the
165               ** user entry u1, select max() will chose 32772 which,
166               ** ANDed with 1 gives 0, i.e., sp_stored_procedures will
167               ** not display this particular procedure to the user.
168               **
169               ** When the user u2 invokes sp_stored_procedures, there is
170               ** only one entry for u2, which is the entry for the group
171               ** g12, and so this entry will be selected thus allowing
172               ** the procedure in question to be displayed.
173               **
174               ** NOTE: With the extension of the uid's into negative space, 
175               ** and uid limits going beyond 64K, the original expression 
176               ** has been modified from
177               ** ((select max(((sign(uid)*abs(uid-16383))*2)
178               **		+ ((protecttype/2)^1))
179               ** to
180               ** ((select max((abs(uid-u.gid)*2)
181               **		+ ((protecttype/2)^1))
182               ** 
183               ** Notice that multiplying by 2 makes the number an
184               ** even number (meaning the last digit is 0) so what
185               ** matters at the end is (protecttype/2)^1.
186               **
187               */
188   
189               or ((select max((abs(p.uid - u2.gid) * 2) + ((p.protecttype / 2) ^ 1))
190                   from sysprotects p, sysusers u2
191                   where p.id = o.id
192                       and u2.uid = user_id()
193                       /*
194                       ** get rows for public, current users, user's groups
195                       */
196                       and (p.uid = 0 /* get rows for public */
197                           or p.uid = user_id() /* current user */
198                           or p.uid = u2.gid) /* users group */
199   
200                       /*
201                       ** check for SELECT, EXECUTE privilege.
202                       */
203                       and (p.action in (193, 224)) /* check for SELECT,EXECUTE 
204                   ** privilege 
205                   */
206                   ) & 1 /* more magic...normalize GRANT */
207               ) = 1 /* final magic...compare Grants	*/
208               /*
209               ** If one of any user defined roles or contained roles for the
210               ** user has permission, the user has the permission
211               */
212               or exists (select 1
213                   from sysprotects p1,
214                       master.dbo.syssrvroles srvro,
215                       sysroles ro
216                   where p1.id = o.id
217                       and p1.uid = ro.lrid
218                       and ro.id = srvro.srid
219                       and has_role(srvro.name, 1) > 0
220                       and p1.action = 224))
221       order by procedure_qualifier, procedure_owner,
222           procedure_name
223   


exec sp_procxmode 'sp_stored_procedures', 'AnyMode'
go

Grant Execute on sp_stored_procedures to public
go
RESULT SETS
sp_stored_procedures_rset_001

DEFECTS
 MEST 4 Empty String will be replaced by Single Space 36
 MEST 4 Empty String will be replaced by Single Space 42
 MEST 4 Empty String will be replaced by Single Space 43
 MINU 4 Unique Index with nullable columns sybsystemprocs..sysprotects sybsystemprocs..sysprotects
 QCAS 4 Cartesian product with single row between tables sybsystemprocs..sysobjects o and [sybsystemprocs..sysusers u], 5 tables with rc=1 94
 QPUI 4 Join or Sarg with Un-Rooted Partial Index Use SARG Candidate index: sysprocedures.csysprocedures unique clustered
(id, number, type, sequence)
Intersection: {sequence}
103
 QPUI 4 Join or Sarg with Un-Rooted Partial Index Use JOIN Candidate index: sysprotects.csysprotects unique clustered
(id, action, grantor, uid, protecttype)
Intersection: {uid}
Uncovered: [id, grantor, protecttype]
198
 QPUI 4 Join or Sarg with Un-Rooted Partial Index Use SARG Candidate index: sysprotects.csysprotects unique clustered
(id, action, grantor, uid, protecttype)
Intersection: {action}
220
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 220
 MGTP 3 Grant to public master..syssrvroles  
 MGTP 3 Grant to public sybsystemprocs..sp_stored_procedures  
 MGTP 3 Grant to public sybsystemprocs..sysobjects  
 MGTP 3 Grant to public sybsystemprocs..sysprocedures  
 MGTP 3 Grant to public sybsystemprocs..sysprotects  
 MGTP 3 Grant to public sybsystemprocs..sysroles  
 MGTP 3 Grant to public sybsystemprocs..sysusers  
 MUCO 3 Useless Code Useless Brackets 54
 MUCO 3 Useless Code Useless Brackets 86
 MUCO 3 Useless Code Useless Brackets 189
 QISO 3 Set isolation level 27
 QNAJ 3 Not using ANSI Inner Join 101
 QNAJ 3 Not using ANSI Inner Join 190
 QNAJ 3 Not using ANSI Inner Join 213
 QPNC 3 No column in condition 111
 QPNC 3 No column in condition 189
 MRST 2 Result Set Marker 94
 MSUB 2 Subquery Marker 70
 MSUC 2 Correlated Subquery Marker 189
 MSUC 2 Correlated Subquery Marker 212
 MTR1 2 Metrics: Comments Ratio Comments: 68% 10
 MTR2 2 Metrics: Cyclomatic Complexity Cyclo: 13 = 13dec - 2exi + 2 10
 MTR3 2 Metrics: Query Complexity Complexity: 67 10
 PRED_QUERY_COLLECTION 2 {o=sybsystemprocs..sysobjects, p=sybsystemprocs..sysprocedures} 0 94
 PRED_QUERY_COLLECTION 2 {o=sybsystemprocs..sysobjects, p=sybsystemprocs..sysprotects, u=sybsystemprocs..sysusers} 0 189
 PRED_QUERY_COLLECTION 2 {o=sybsystemprocs..sysobjects, p=sybsystemprocs..sysprotects, r=sybsystemprocs..sysroles, s=master..syssrvroles} 0 212

DEPENDENCIES
PROCS AND TABLES USED
reads table master..syssrvroles (1)  
reads table sybsystemprocs..sysroles  
reads table sybsystemprocs..sysusers  
reads table sybsystemprocs..sysprocedures  
reads table sybsystemprocs..sysprotects  
reads table sybsystemprocs..sysobjects