DatabaseProcApplicationCreatedLinks
sybsystemprocssp_odbc_fkeys  31 Aug 14Defects Dependencies

1     
2     /* sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
3     /*
4     ** note: there is one raiserror message: 18040
5     **
6     ** messages for "sp_odbc_fkeys"               18039, 18040
7     **
8     ** 17461, "Object does not exist in this database." 
9     ** 18040, "Catalog procedure %1! can not be run in a transaction.", sp_odbc_fkeys
10    ** 18043 " Primary key table name or foreign key table name or both must be 
11    ** given"
12    ** 18044, "%1! table qualifier must be name of current database." [Primary
13    ** key | Foreign key]
14    **
15    */
16    CREATE PROCEDURE sp_odbc_fkeys
17        @pktable_name varchar(255) = null,
18        @pktable_owner varchar(32) = null,
19        @pktable_qualifier varchar(32) = null,
20        @fktable_name varchar(255) = null,
21        @fktable_owner varchar(32) = null,
22        @fktable_qualifier varchar(32) = null
23    as
24        declare @ftabid int, @ptabid int, @constrid int, @keycnt int, @i int
25        declare @fokey1 int, @fokey2 int, @fokey3 int, @fokey4 int, @fokey5 int
26        declare @fokey6 int, @fokey7 int, @fokey8 int, @fokey9 int, @fokey10 int
27        declare @fokey11 int, @fokey12 int, @fokey13 int, @fokey14 int, @fokey15 int
28        declare @refkey1 int, @refkey2 int, @refkey3 int, @refkey4 int, @refkey5 int
29        declare @refkey6 int, @refkey7 int, @refkey8 int, @refkey9 int, @refkey10 int
30        declare @refkey11 int, @refkey12 int, @refkey13 int, @refkey14 int
31        declare @refkey15 int, @refkey16 int, @fokey16 int, @status int
32        declare @msg varchar(1024)
33        declare @msg2 varchar(1024)
34        declare @ordpkey int
35        declare @notDeferrable smallint
36        declare @startedInTransaction bit
37        if (@@trancount > 0)
38            select @startedInTransaction = 1
39        else
40            select @startedInTransaction = 0
41    
42        set nocount on
43    
44        if (@@trancount = 0)
45        begin
46            set chained off
47        end
48    
49        set transaction isolation level 1
50    
51        if (@startedInTransaction = 1)
52            save transaction odbc_keep_temptable_tx
53    
54        select @notDeferrable = 7
55    
56        if (@pktable_name is null) and (@fktable_name is null)
57        begin
58            /* If neither primary key nor foreign key table names given */
59            /* 
60            ** 18043 "Primary key table name or foreign key table name 
61            ** or both must be given"
62            */
63            raiserror 18043
64            return (1)
65        end
66    
67        if @fktable_qualifier is not null
68        begin
69            if db_name() != @fktable_qualifier
70            begin
71                /* If qualifier doesn't match current database */
72                /* 18044 "%1! Table qualifier must be name of current database"
73                ** 18050 "Foreign key"
74                */
75                exec sp_getmessage 18050, @msg2 output
76                raiserror 18044, @msg2
77                return (1)
78            end
79        end
80        else
81        begin
82            /*
83            ** Now make sure that foreign table qualifier is pointing to the
84            ** current database in case it is not specified.
85            */
86            select @fktable_qualifier = db_name()
87        end
88    
89        if @pktable_qualifier is not null
90        begin
91            if db_name() != @pktable_qualifier
92            begin
93                /* If qualifier doesn't match current database */
94                /* 18044 "%1! Table qualifier must be name of current database"
95                ** 18051 "Primary Key"
96                */
97                exec sp_getmessage 18051, @msg2 output
98                raiserror 18044, @msg2
99                return (1)
100           end
101       end
102       else
103       begin
104           /*
105           ** Now make sure that primary table qualifier is pointing to the
106           ** current database in case it is not specified.
107           */
108           select @pktable_qualifier = db_name()
109       end
110   
111   
112       create table #opid(pid int, uid int, name varchar(255))
113       create table #ofid(fid int, uid int, name varchar(255))
114   
115       /* we will sort by fkey		*/
116       /* unless pktable is null	*/
117   
118       select @ordpkey = 0
119   
120       if @pktable_name is not null
121       begin
122   
123           if (@pktable_owner is null)
124           begin
125               /* 
126               ** owner is NULL, so default to the current user
127               ** who owns this table, otherwise default to dbo
128               ** who owns this table.
129               */
130               insert into #opid
131               select id, uid, name
132               from sysobjects
133               where name = @pktable_name and uid = user_id()
134                   and type in ("S", "U")
135   
136               /* 
137               ** If the current user does not own the table, see
138               ** if the DBO of the current database owns the table.
139               */
140   
141               if ((select count(*) from #opid) = 0)
142               begin
143                   insert into #opid
144                   select id, uid, name
145                   from sysobjects
146                   where name = @pktable_name and uid = 1
147                       and type in ("S", "U")
148               end
149           end
150           else
151           begin
152               insert into #opid
153               select id, uid, name
154               from sysobjects
155               where name = @pktable_name
156                   and uid = user_id(@pktable_owner)
157                   and type in ("S", "U")
158           end
159       end
160       else
161       begin
162           if (@pktable_owner is null)
163           begin
164               /* 
165               ** If neither pktable_name nor pktable_owner is specified,
166               ** then we are interested in every user or system table.
167               */
168               insert into #opid
169               select id, uid, name
170               from sysobjects
171               where type in ("S", "U")
172           end
173           else
174           begin
175               insert into #opid
176               select id, uid, name
177               from sysobjects
178               where uid = user_id(@pktable_owner)
179                   and type in ("S", "U")
180           end
181       end
182   
183       if @fktable_name is not null
184       begin
185           /* sort by pkey	*/
186           select @ordpkey = 1
187   
188           if (@fktable_owner is null)
189           begin
190               /* 
191               ** owner is NULL, so default to the current user
192               ** who owns this table, otherwise default to dbo
193               ** who owns this table.
194               */
195               insert into #ofid
196               select id, uid, name
197               from sysobjects
198               where name = @fktable_name and uid = user_id()
199                   and type in ("S", "U")
200   
201               /* 
202               ** If the current user does not own the table, see
203               ** if the DBO of the current database owns the table.
204               */
205   
206               if ((select count(*) from #opid) = 0)
207               begin
208                   insert into #ofid
209                   select id, uid, name
210                   from sysobjects
211                   where name = @fktable_name and uid = 1
212                       and type in ("S", "U")
213               end
214           end
215           else
216           begin
217               insert into #ofid
218               select id, uid, name
219               from sysobjects
220               where name = @fktable_name
221                   and uid = user_id(@fktable_owner)
222                   and type in ("S", "U")
223           end
224       end
225       else
226       begin
227           if (@fktable_owner is null)
228           begin
229               /* 
230               ** If neither fktable_name nor fktable_owner is specified,
231               ** then we are interested in every user table or systme 
232               ** table.
233               */
234               insert into #ofid
235               select id, uid, name
236               from sysobjects
237               where type in ("S", "U")
238           end
239           else
240           begin
241               insert into #ofid
242               select id, uid, name
243               from sysobjects
244               where uid = user_id(@fktable_owner)
245                   and type in ("S", "U")
246           end
247       end
248   
249       if (((select count(*) from #ofid) = 0) or
250               ((select count(*) from #opid) = 0))
251       begin
252           /* 17461, "Object does not exist in this database." */
253           raiserror 17461
254           return (1)
255       end
256   
257       create table #ofkey_res(PKTABLE_CAT varchar(32),
258           PKTABLE_SCHEM varchar(32),
259           PKTABLE_NAME varchar(255),
260           PKCOLUMN_NAME varchar(255),
261           FKTABLE_CAT varchar(32),
262           FKTABLE_SCHEM varchar(32),
263           FKTABLE_NAME varchar(255),
264           FKCOLUMN_NAME varchar(255),
265           KEY_SEQ smallint,
266           UPDATE_RULE smallint,
267           DELETE_RULE smallint,
268           FK_NAME varchar(255),
269           PK_NAME varchar(255))
270       create table #opkeys(seq int, keys varchar(255) null)
271       create table #ofkeys(seq int, keys varchar(255) null)
272   
273       /*
274       ** Since there are possibly multiple rows in sysreferences
275       ** that describe foreign and primary key relationships among
276       ** two tables, so we declare a cursor on the selection from
277       ** sysreferences and process the output at row by row basis.
278       */
279   
280       declare curs_sysreferences cursor
281       for
282       select tableid, reftabid, constrid, keycnt,
283           fokey1, fokey2, fokey3, fokey4, fokey5, fokey6, fokey7, fokey8,
284           fokey9, fokey10, fokey11, fokey12, fokey13, fokey14, fokey15,
285           fokey16, refkey1, refkey2, refkey3, refkey4, refkey5,
286           refkey6, refkey7, refkey8, refkey9, refkey10, refkey11,
287           refkey12, refkey13, refkey14, refkey15, refkey16
288       from sysreferences
289       where tableid in (
290               select fid from #ofid)
291           and reftabid in (
292               select pid from #opid)
293           and frgndbname is NULL and pmrydbname is NULL
294       for read only
295   
296       open curs_sysreferences
297   
298       fetch curs_sysreferences into @ftabid, @ptabid, @constrid, @keycnt, @fokey1,
299           @fokey2, @fokey3, @fokey4, @fokey5, @fokey6, @fokey7, @fokey8,
300           @fokey9, @fokey10, @fokey11, @fokey12, @fokey13, @fokey14, @fokey15,
301           @fokey16, @refkey1, @refkey2, @refkey3, @refkey4, @refkey5, @refkey6,
302           @refkey7, @refkey8, @refkey9, @refkey10, @refkey11, @refkey12,
303           @refkey13, @refkey14, @refkey15, @refkey16
304   
305       while (@@sqlstatus = 0)
306       begin
307           /*
308           ** For each row of sysreferences which describes a foreign-
309           ** primary key relationship, do the following.
310           */
311   
312           /*
313           ** First store the column names that belong to primary keys
314           ** in table #pkeys for later retrieval.
315           */
316   
317           delete #opkeys
318           insert #opkeys values (1, col_name(@ptabid, @refkey1))
319           insert #opkeys values (2, col_name(@ptabid, @refkey2))
320           insert #opkeys values (3, col_name(@ptabid, @refkey3))
321           insert #opkeys values (4, col_name(@ptabid, @refkey4))
322           insert #opkeys values (5, col_name(@ptabid, @refkey5))
323           insert #opkeys values (6, col_name(@ptabid, @refkey6))
324           insert #opkeys values (7, col_name(@ptabid, @refkey7))
325           insert #opkeys values (8, col_name(@ptabid, @refkey8))
326           insert #opkeys values (9, col_name(@ptabid, @refkey9))
327           insert #opkeys values (10, col_name(@ptabid, @refkey10))
328           insert #opkeys values (11, col_name(@ptabid, @refkey11))
329           insert #opkeys values (12, col_name(@ptabid, @refkey12))
330           insert #opkeys values (13, col_name(@ptabid, @refkey13))
331           insert #opkeys values (14, col_name(@ptabid, @refkey14))
332           insert #opkeys values (15, col_name(@ptabid, @refkey15))
333           insert #opkeys values (16, col_name(@ptabid, @refkey16))
334   
335           /*
336           ** Second store the column names that belong to foreign keys
337           ** in table #fkeys for later retrieval.
338           */
339   
340           delete #ofkeys
341           insert #ofkeys values (1, col_name(@ftabid, @fokey1))
342           insert #ofkeys values (2, col_name(@ftabid, @fokey2))
343           insert #ofkeys values (3, col_name(@ftabid, @fokey3))
344           insert #ofkeys values (4, col_name(@ftabid, @fokey4))
345           insert #ofkeys values (5, col_name(@ftabid, @fokey5))
346           insert #ofkeys values (6, col_name(@ftabid, @fokey6))
347           insert #ofkeys values (7, col_name(@ftabid, @fokey7))
348           insert #ofkeys values (8, col_name(@ftabid, @fokey8))
349           insert #ofkeys values (9, col_name(@ftabid, @fokey9))
350           insert #ofkeys values (10, col_name(@ftabid, @fokey10))
351           insert #ofkeys values (11, col_name(@ftabid, @fokey11))
352           insert #ofkeys values (12, col_name(@ftabid, @fokey12))
353           insert #ofkeys values (13, col_name(@ftabid, @fokey13))
354           insert #ofkeys values (14, col_name(@ftabid, @fokey14))
355           insert #ofkeys values (15, col_name(@ftabid, @fokey15))
356           insert #ofkeys values (16, col_name(@ftabid, @fokey16))
357   
358           /* 
359           ** For each column of the current foreign-primary key relation,
360           ** create a row into result table: #fkey_res.
361           */
362   
363           select @i = 1
364           while (@i <= @keycnt)
365           begin
366               insert into #ofkey_res
367               select @pktable_qualifier,
368                       (select user_name(uid) from #opid where pid = @ptabid),
369                   object_name(@ptabid),
370                       (select keys from #opkeys where seq = @i),
371                   @fktable_qualifier,
372                       (select user_name(uid) from #ofid where fid = @ftabid),
373                   object_name(@ftabid),
374                       (select keys from #ofkeys where seq = @i), @i,
375                   1, 1,
376                   /* Foreign Key */
377                   object_name(@constrid),
378                       /* Primary key name */
379                       (select name from sysindexes where id = @ptabid
380                           and status > 2048 and status < 32768)
381               select @i = @i + 1
382           end
383   
384           /* 
385           ** Go to the next foreign-primary key relationship if any.
386           */
387   
388           fetch curs_sysreferences into @ftabid, @ptabid, @constrid, @keycnt, @fokey1,
389               @fokey2, @fokey3, @fokey4, @fokey5, @fokey6, @fokey7, @fokey8,
390               @fokey9, @fokey10, @fokey11, @fokey12, @fokey13, @fokey14, @fokey15,
391               @fokey16, @refkey1, @refkey2, @refkey3, @refkey4, @refkey5, @refkey6,
392               @refkey7, @refkey8, @refkey9, @refkey10, @refkey11, @refkey12,
393               @refkey13, @refkey14, @refkey15, @refkey16
394       end
395   
396       close curs_sysreferences
397       deallocate cursor curs_sysreferences
398   
399       /*
400       ** Everything is now in the result table #fkey_res, so go ahead
401       ** and select from the table now.
402       */
403   
404       /* if @ordpkey = 0 sort by fkey */
405       /* else sort by pkey		*/
406       if @ordpkey = 0
407       begin
408           select PKTABLE_CAT, PKTABLE_SCHEM, PKTABLE_NAME,
409               PKCOLUMN_NAME, FKTABLE_CAT, FKTABLE_SCHEM,
410               FKTABLE_NAME, FKCOLUMN_NAME, KEY_SEQ, UPDATE_RULE, DELETE_RULE,
411               FK_NAME, PK_NAME, @notDeferrable as DEFERRABILITY
412           from #ofkey_res
413           order by FKTABLE_NAME, FKTABLE_SCHEM, KEY_SEQ, FKTABLE_CAT
414       end
415       else
416       begin
417           select PKTABLE_CAT, PKTABLE_SCHEM, PKTABLE_NAME,
418               PKCOLUMN_NAME, FKTABLE_CAT, FKTABLE_SCHEM,
419               FKTABLE_NAME, FKCOLUMN_NAME, KEY_SEQ, UPDATE_RULE, DELETE_RULE,
420               FK_NAME, PK_NAME, @notDeferrable as DEFERRABILITY
421           from #ofkey_res
422           order by PKTABLE_NAME, PKTABLE_SCHEM, KEY_SEQ, PKTABLE_CAT
423       end
424   
425       drop table #opkeys
426       drop table #ofkeys
427       drop table #ofkey_res
428       if (@startedInTransaction = 1)
429           rollback transaction odbc_keep_temptable_tx
430   
431   


exec sp_procxmode 'sp_odbc_fkeys', 'AnyMode'
go

Grant Execute on sp_odbc_fkeys to public
go
RESULT SETS
sp_odbc_fkeys_rset_002
sp_odbc_fkeys_rset_001

DEFECTS
 MTYP 4 Assignment type mismatch KEY_SEQ: smallint = int 374
 QCSC 4 Costly 'select count()', use 'exists()' 141
 QCSC 4 Costly 'select count()', use 'exists()' 206
 QCSC 4 Costly 'select count()', use 'exists()' 249
 QCSC 4 Costly 'select count()', use 'exists()' 250
 QPUI 4 Join or Sarg with Un-Rooted Partial Index Use SARG Candidate index: sysobjects.ncsysobjects unique
(name, uid)
Intersection: {uid}
178
 QPUI 4 Join or Sarg with Un-Rooted Partial Index Use SARG Candidate index: sysobjects.ncsysobjects unique
(name, uid)
Intersection: {uid}
244
 QPUI 4 Join or Sarg with Un-Rooted Partial Index Use SARG Candidate index: sysreferences.csysreferences clustered
(tableid, frgndbname)
Intersection: {frgndbname}
293
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 380
 TNOU 4 Table with no unique index sybsystemprocs..sysreferences sybsystemprocs..sysreferences
 MGTP 3 Grant to public sybsystemprocs..sp_odbc_fkeys  
 MGTP 3 Grant to public sybsystemprocs..sysindexes  
 MGTP 3 Grant to public sybsystemprocs..sysobjects  
 MGTP 3 Grant to public sybsystemprocs..sysreferences  
 MNER 3 No Error Check should check return value of exec 75
 MNER 3 No Error Check should check return value of exec 97
 MNER 3 No Error Check should check @@error after insert 130
 MNER 3 No Error Check should check @@error after insert 143
 MNER 3 No Error Check should check @@error after insert 152
 MNER 3 No Error Check should check @@error after insert 168
 MNER 3 No Error Check should check @@error after insert 175
 MNER 3 No Error Check should check @@error after insert 195
 MNER 3 No Error Check should check @@error after insert 208
 MNER 3 No Error Check should check @@error after insert 217
 MNER 3 No Error Check should check @@error after insert 234
 MNER 3 No Error Check should check @@error after insert 241
 MNER 3 No Error Check should check @@error after delete 317
 MNER 3 No Error Check should check @@error after insert 318
 MNER 3 No Error Check should check @@error after insert 319
 MNER 3 No Error Check should check @@error after insert 320
 MNER 3 No Error Check should check @@error after insert 321
 MNER 3 No Error Check should check @@error after insert 322
 MNER 3 No Error Check should check @@error after insert 323
 MNER 3 No Error Check should check @@error after insert 324
 MNER 3 No Error Check should check @@error after insert 325
 MNER 3 No Error Check should check @@error after insert 326
 MNER 3 No Error Check should check @@error after insert 327
 MNER 3 No Error Check should check @@error after insert 328
 MNER 3 No Error Check should check @@error after insert 329
 MNER 3 No Error Check should check @@error after insert 330
 MNER 3 No Error Check should check @@error after insert 331
 MNER 3 No Error Check should check @@error after insert 332
 MNER 3 No Error Check should check @@error after insert 333
 MNER 3 No Error Check should check @@error after delete 340
 MNER 3 No Error Check should check @@error after insert 341
 MNER 3 No Error Check should check @@error after insert 342
 MNER 3 No Error Check should check @@error after insert 343
 MNER 3 No Error Check should check @@error after insert 344
 MNER 3 No Error Check should check @@error after insert 345
 MNER 3 No Error Check should check @@error after insert 346
 MNER 3 No Error Check should check @@error after insert 347
 MNER 3 No Error Check should check @@error after insert 348
 MNER 3 No Error Check should check @@error after insert 349
 MNER 3 No Error Check should check @@error after insert 350
 MNER 3 No Error Check should check @@error after insert 351
 MNER 3 No Error Check should check @@error after insert 352
 MNER 3 No Error Check should check @@error after insert 353
 MNER 3 No Error Check should check @@error after insert 354
 MNER 3 No Error Check should check @@error after insert 355
 MNER 3 No Error Check should check @@error after insert 356
 MNER 3 No Error Check should check @@error after insert 366
 MUCO 3 Useless Code Useless Brackets 37
 MUCO 3 Useless Code Useless Brackets 44
 MUCO 3 Useless Code Useless Brackets 51
 MUCO 3 Useless Code Useless Brackets 64
 MUCO 3 Useless Code Useless Brackets 77
 MUCO 3 Useless Code Useless Brackets 99
 MUCO 3 Useless Code Useless Brackets 123
 MUCO 3 Useless Code Useless Brackets 141
 MUCO 3 Useless Code Useless Brackets 162
 MUCO 3 Useless Code Useless Brackets 188
 MUCO 3 Useless Code Useless Brackets 206
 MUCO 3 Useless Code Useless Brackets 227
 MUCO 3 Useless Code Useless Brackets 249
 MUCO 3 Useless Code Useless Brackets 254
 MUCO 3 Useless Code Useless Brackets 305
 MUCO 3 Useless Code Useless Brackets 364
 MUCO 3 Useless Code Useless Brackets 428
 MUIN 3 Column created using implicit nullability 112
 MUIN 3 Column created using implicit nullability 113
 MUIN 3 Column created using implicit nullability 257
 MUIN 3 Column created using implicit nullability 270
 MUIN 3 Column created using implicit nullability 271
 QCRS 3 Conditional Result Set 408
 QCRS 3 Conditional Result Set 417
 QISO 3 Set isolation level 49
 QJWT 3 Join or Sarg Without Index on temp table 289
 QJWT 3 Join or Sarg Without Index on temp table 291
 QPRI 3 Join or Sarg with Rooted Partial Index Use SARG Candidate index: sysindexes.csysindexes unique clustered
(id, indid)
Intersection: {id}
379
 VUNU 3 Variable is not used @status 31
 VUNU 3 Variable is not used @msg 32
 CRDO 2 Read Only Cursor Marker (has for read only clause) 282
 MRST 2 Result Set Marker 408
 MRST 2 Result Set Marker 417
 MSUB 2 Subquery Marker 368
 MSUB 2 Subquery Marker 370
 MSUB 2 Subquery Marker 372
 MSUB 2 Subquery Marker 374
 MSUB 2 Subquery Marker 379
 MTR1 2 Metrics: Comments Ratio Comments: 24% 16
 MTR2 2 Metrics: Cyclomatic Complexity Cyclo: 23 = 26dec - 5exi + 2 16
 MTR3 2 Metrics: Query Complexity Complexity: 252 16

DEPENDENCIES
PROCS AND TABLES USED
read_writes table tempdb..#opkeys (1) 
read_writes table tempdb..#ofkey_res (1) 
calls proc sybsystemprocs..sp_getmessage  
   reads table master..sysmessages (1)  
   calls proc sybsystemprocs..sp_validlang  
      reads table master..syslanguages (1)  
   reads table sybsystemprocs..sysusermessages  
   reads table master..syslanguages (1)  
read_writes table tempdb..#opid (1) 
reads table sybsystemprocs..sysreferences  
reads table sybsystemprocs..sysobjects  
reads table sybsystemprocs..sysindexes  
read_writes table tempdb..#ofid (1) 
read_writes table tempdb..#ofkeys (1)