DatabaseProcApplicationCreatedLinks
sybsystemprocssp_odbc_tables  31 Aug 14Defects Dependencies

1     
2     /* Sccsid = "%Z% generic/sproc/%M% %I% %G%" */
3     /*	10.0	1.1	06/16/93	sproc/tables */
4     
5     /*
6     ** Messages for "sp_odbc_tables"         18039
7     **
8     ** 17676, "This may be a temporary object. Please execute procedure from your 
9     **         temporary database."
10    **
11    ** 18039, "Table qualifier must be name of current database"
12    **
13    */
14    create procedure sp_odbc_tables
15        @table_name varchar(771) = null,
16        @table_owner varchar(32) = null,
17        @table_qualifier varchar(32) = null,
18        @table_type varchar(100) = null
19    as
20    
21        declare @type1 varchar(3)
22        declare @tableindex int
23    
24    
25        if @@trancount = 0
26        begin
27            set chained off
28        end
29    
30        set transaction isolation level 1
31    
32        /* temp table */
33        if (@table_name like "#%" and
34                db_name() != db_name(tempdb_id()))
35        begin
36            /*
37            ** Can return data about temp. tables only in session's temporary db
38            */
39            raiserror 17676
40            return (1)
41        end
42    
43        /*
44        ** Special feature #1:	enumerate databases when owner and name
45        ** are blank but qualifier is explicitly '%'.  
46        */
47        if @table_qualifier = '%' and
48            (@table_owner = '' or @table_owner is null) and
49            (@table_name = '' or @table_name is null)
50        begin
51    
52            /*
53            ** If enumerating databases 
54            */
55            select
56                TABLE_CAT = name,
57                TABLE_SCHEM = null,
58                TABLE_NAME = null,
59                TABLE_TYPE = 'Database',
60    
61                /*
62                ** Remarks are NULL 
63                */
64                REMARKS = convert(varchar(254), null)
65    
66            from master..sysdatabases
67    
68            /*
69            ** eliminate MODEL database 
70            */
71            where name != 'model'
72            order by TABLE_CAT
73        end
74    
75        /*
76        ** Special feature #2:	enumerate owners when qualifier and name
77        ** are blank but owner is explicitly '%'.
78        */
79        else if @table_qualifier = '' and
80            @table_owner = '%' and
81            (@table_name = '' or @table_name is null)
82        begin
83    
84            /*
85            ** If enumerating owners 
86            */
87            select distinct
88                TABLE_CAT = null,
89                TABLE_SCHEM = user_name(uid),
90                TABLE_NAME = null,
91                TABLE_TYPE = 'Owner',
92    
93                /*
94                ** Remarks are NULL 
95                */
96                REMARKS = convert(varchar(254), null)
97    
98            from sysobjects
99            order by TABLE_SCHEM
100       end
101       else
102       begin
103           /*
104           ** end of special features -- do normal processing 
105           */
106           if @table_qualifier is not null
107           begin
108               if db_name() != @table_qualifier
109               begin
110                   if @table_qualifier = ''
111                   begin
112   
113                       /*
114                       ** If empty qualifier supplied
115                       ** Force an empty result set 
116                       */
117                       select @table_name = ''
118                       select @table_owner = ''
119                   end
120                   else
121                   begin
122   
123                       /*
124                       ** If qualifier doesn't match current 
125                       ** database. 
126                       */
127                       raiserror 18039
128                       return 1
129                   end
130               end
131           end
132           if @table_type is null
133           begin
134   
135               /*
136               ** Select all ODBC supported table types 
137               */
138               select @type1 = 'SUV'
139           end
140           else
141           begin
142               /*
143               ** TableType are case sensitive if CS server 
144               */
145               select @type1 = null
146   
147               /*
148               ** Add System Tables 
149               */
150               if (charindex("'SYSTEM TABLE'", @table_type) != 0)
151                   select @type1 = @type1 + 'S'
152   
153               /*
154               ** Add User Tables 
155               */
156               if (charindex("'TABLE'", @table_type) != 0)
157                   select @type1 = @type1 + 'U'
158   
159               /*
160               ** Add Views 
161               */
162               if (charindex("'VIEW'", @table_type) != 0)
163                   select @type1 = @type1 + 'V'
164           end
165           if @table_name is null
166           begin
167   
168               /*
169               ** If table name not supplied, match all 
170               */
171               select @table_name = '%'
172           end
173           else
174           begin
175               if (@table_owner is null) and
176                   (charindex('%', @table_name) = 0)
177               begin
178   
179                   /*
180                   ** If owner not specified and table is specified 
181                   */
182                   if exists (select * from sysobjects
183                           where uid = user_id()
184                               and id = object_id(@table_name)
185                               and (type = 'U' or type = 'V'
186                                   or type = 'S'))
187                   begin
188   
189                       /*
190                       ** Override supplied owner w/owner of table 
191                       */
192                       select @table_owner = user_name()
193                   end
194               end
195           end
196   
197   
198           /*
199           ** If no owner supplied, force wildcard 
200           */
201           if @table_owner is null
202               select @table_owner = '%'
203           select
204               TABLE_CAT = db_name(),
205               TABLE_SCHEM = user_name(o.uid),
206               TABLE_NAME = o.name,
207               TABLE_TYPE = rtrim(
208                   substring('SYSTEM TABLE            TABLE       VIEW       ',
209                       /*
210                       ** 'S'=0,'U'=2,'V'=3 
211                       */
212                       (ascii(o.type) - 83) * 12 + 1, 12)),
213   
214               /*
215               ** Remarks are NULL
216               */
217               REMARKS = convert(varchar(254), null)
218   
219           from sysobjects o
220           where
221               /* Special case for temp. tables.  Match ids */
222               (o.name like @table_name or o.id = object_id(@table_name))
223               and user_name(o.uid) like @table_owner
224   
225               /*
226               ** Only desired types
227               */
228               and charindex(substring(o.type, 1, 1), @type1) != 0
229               and (
230                   suser_id() = 1 /* User is the System Administrator */
231                   or o.uid = user_id() /* User created the object */
232                   /* here's the magic..select the highest
233                   ** precedence of permissions in the
234                   ** order (user,group,public)
235                   */
236   
237                   /*
238                   ** The value of protecttype is
239                   **
240                   **      0  for grant with grant
241                   **      1  for grant and,
242                   **      2  for revoke
243                   **
244                   ** As protecttype is of type tinyint, protecttype/2 is
245                   ** integer division and will yield 0 for both types of
246                   ** grants and will yield 1 for revoke, i.e., when
247                   ** the value of protecttype is 2.  The XOR (^) operation
248                   ** will reverse the bits and thus (protecttype/2)^1 will
249                   ** yield a value of 1 for grants and will yield a
250                   ** value of zero for revoke.
251                   **
252                   ** For groups, uid = gid. We shall use this to our advantage.
253                   **
254                   ** If there are several entries in the sysprotects table
255                   ** with the same Object ID, then the following expression
256                   ** will prefer an individual uid entry over a group entry
257                   **
258                   ** For example, let us say there are two users u1 and u2
259                   ** with uids 4 and 5 respectiveley and both u1 and u2
260                   ** belong to a group g12 whose uid is 16390.  table t1
261                   ** is owned by user u0 and user u0 performs the following
262                   ** actions:
263                   **
264                   **      grant select on t1 to g12
265                   **      revoke select on t1 from u1
266                   **
267                   ** There will be two entries in sysprotects for the object t1,
268                   ** one for the group g12 where protecttype = grant (1) and
269                   ** one for u1 where protecttype = revoke (2).
270                   **
271                   ** For the group g12, the following expression will
272                   ** evaluate to:
273                   **
274                   **      ((abs(16390-16390)*2) + ((1/2)^1)
275                   **      = ((0) + (0)^1) = 0 + 1 = 1
276                   **
277                   ** For the user entry u1, it will evaluate to:
278                   **
279                   **      (((+)*abs(4-16390)*2) + ((2/2)^1))
280                   **      = (abs(-16386)*2 + (1)^1)
281                   **      = 16386*2 + 0 = 32772
282                   **
283                   ** As the expression evaluates to a bigger number for the
284                   ** user entry u1, select max() will chose 32772 which,
285                   ** ANDed with 1 gives 0, i.e., sp_odbc_tables will not display
286                   ** this particular table to the user.
287                   **
288                   ** When the user u2 invokes sp_odbc_tables, there is only one
289                   ** entry for u2, which is the entry for the group g12, and
290                   ** so the group entry will be selected thus allowing the
291                   ** table t1 to be displayed.
292                   **
293                   ** ((select max((abs(uid-u.gid)*2)
294                   ** 		+ ((protecttype/2)^1))
295                   **
296                   ** Notice that multiplying by 2 makes the number an
297                   ** even number (meaning the last digit is 0) so what
298                   ** matters at the end is (protecttype/2)^1.
299                   **
300                   **/
301   
302                   or ((select max((abs(p.uid - u2.gid) * 2) + ((p.protecttype / 2) ^ 1))
303                       from sysprotects p, sysusers u2
304                       where p.id = o.id /* outer join to correlate
305                           ** with all rows in sysobjects
306                           */
307                           and u2.uid = user_id()
308                           /*
309                           ** get rows for public, current users, user's groups
310                           */
311                           and (p.uid = 0 or /* public */
312                               p.uid = user_id() or /* current user */
313                               p.uid = u2.gid) /* users group */
314   
315                           /*
316                           ** check for SELECT, EXECUTE privilege.
317                           */
318                           and (p.action in (193, 224))) & 1
319   
320                   /*
321                   ** more magic...normalise GRANT
322                   ** and final magic...compare
323                   ** Grants.
324                   */
325                   ) = 1
326                   /*
327                   ** If one of any user defined roles or contained roles for the
328                   ** user has permission, the user has the permission
329                   */
330                   or exists (select 1
331                       from sysprotects p1,
332                           master.dbo.syssrvroles srvro,
333                           sysroles ro
334                       where p1.id = o.id
335                           and p1.uid = ro.lrid
336                           and ro.id = srvro.srid
337                           and has_role(srvro.name, 1) > 0
338                           and p1.action = 193))
339           order by TABLE_TYPE, TABLE_CAT, TABLE_SCHEM, TABLE_NAME
340   
341       end
342   
343   


exec sp_procxmode 'sp_odbc_tables', 'AnyMode'
go

Grant Execute on sp_odbc_tables to public
go
RESULT SETS
sp_odbc_tables_rset_003
sp_odbc_tables_rset_002
sp_odbc_tables_rset_001

DEFECTS
 MEST 4 Empty String will be replaced by Single Space 48
 MEST 4 Empty String will be replaced by Single Space 49
 MEST 4 Empty String will be replaced by Single Space 79
 MEST 4 Empty String will be replaced by Single Space 81
 MEST 4 Empty String will be replaced by Single Space 110
 MEST 4 Empty String will be replaced by Single Space 117
 MEST 4 Empty String will be replaced by Single Space 118
 MINU 4 Unique Index with nullable columns sybsystemprocs..sysprotects sybsystemprocs..sysprotects
 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]
313
 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}
338
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 338
 MGTP 3 Grant to public master..sysdatabases  
 MGTP 3 Grant to public master..syssrvroles  
 MGTP 3 Grant to public sybsystemprocs..sp_odbc_tables  
 MGTP 3 Grant to public sybsystemprocs..sysobjects  
 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 33
 MUCO 3 Useless Code Useless Brackets 40
 MUCO 3 Useless Code Useless Brackets 150
 MUCO 3 Useless Code Useless Brackets 156
 MUCO 3 Useless Code Useless Brackets 162
 MUCO 3 Useless Code Useless Brackets 302
 QCRS 3 Conditional Result Set 55
 QCRS 3 Conditional Result Set 87
 QCRS 3 Conditional Result Set 203
 QISO 3 Set isolation level 30
 QNAJ 3 Not using ANSI Inner Join 303
 QNAJ 3 Not using ANSI Inner Join 331
 QPNC 3 No column in condition 230
 QPNC 3 No column in condition 302
 VUNU 3 Variable is not used @tableindex 22
 MRST 2 Result Set Marker 55
 MRST 2 Result Set Marker 87
 MRST 2 Result Set Marker 203
 MSUB 2 Subquery Marker 182
 MSUC 2 Correlated Subquery Marker 302
 MSUC 2 Correlated Subquery Marker 330
 MTR1 2 Metrics: Comments Ratio Comments: 59% 14
 MTR2 2 Metrics: Cyclomatic Complexity Cyclo: 27 = 28dec - 3exi + 2 14
 MTR3 2 Metrics: Query Complexity Complexity: 95 14
 PRED_QUERY_COLLECTION 2 {o=sybsystemprocs..sysobjects, p=sybsystemprocs..sysprotects, u=sybsystemprocs..sysusers} 0 302
 PRED_QUERY_COLLECTION 2 {o=sybsystemprocs..sysobjects, p=sybsystemprocs..sysprotects, r=sybsystemprocs..sysroles, s=master..syssrvroles} 0 330

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