DatabaseProcApplicationCreatedLinks
sybsystemprocssp_maplogin  31 Aug 14Defects Dependencies

1     
2     /* Sccsid = "%Z% generic/sproc/src/%M% %I% %G%" */
3     
4     /*
5     ** Messages for "sp_maplogin"    
6     **
7     ** 17260, "Can't run '%1!' from within a transaction."
8     ** 17869, "Stored procedure %1 failed because %2 failed in database %3."
9     ** 18294, "User '%1!' is not a local user -- request denied."
10    ** 18388, "You must be in the master database in order to run '%1'!."
11    ** 18409, "The built-in function getdbrepstat() failed."
12    ** 18773, "HA_LOG: HA consistency check failure in '%1!' on the companion server '%2!'"
13    ** 18778, "Unable to find login '%1!' with id '%2!' in syslogins."
14    ** 19257, "The authentication mechanism '%1!' is not valid."
15    ** 19256, "Client authentication mapping updated."
16    ** 19259, "Warning. Authentication mechanism '%1!' is not enabled."
17    ** 19445, "External name '%1!' is already a local login -- map request denied."
18    ** 19447, "User '%1!' allows only '%2!' authentication mechanism to be used -- request denied."
19    ** 19450, "A mapping with authentication mechanism '%1!' is not allowed, only action 'drop' is permitted."
20    ** 19453, "Cannot define a mapping for ALL authentications and ALL logins -- map request denied.
21    ** 19940, "Client authentication mapping overwritten. Previous values were @authentication_mech='%1!', @client_name='%2!' and @login_name='%3!'.
22    */
23    
24    /* 
25    ** IMPORTANT: Please read the following instructions before
26    **   making changes to this stored procedure.
27    **
28    **	To make this stored procedure compatible with High Availability (HA),
29    **	changes to certain system tables must be propagated 
30    **	to the companion server under some conditions.
31    **	The tables include (but are not limited to):
32    **		syslogins, sysservers, sysattributes, systimeranges,
33    **		sysresourcelimits, sysalternates, sysdatabases,
34    **		syslanguages, sysremotelogins, sysloginroles,
35    **		sysalternates (master DB only), systypes (master DB only),
36    **		sysusers (master DB only), sysprotects (master DB only)
37    **	please refer to the HA documentation for detail.
38    **
39    **	Here is what you need to do: 
40    **	For each insert/update/delete statement, add three sections to
41    **	-- start HA transaction prior to the statement
42    **	-- add the statement
43    **	-- add HA synchronization code to propagate the change to the companion
44    **
45    **	For example, if you are adding 
46    **		insert master.dbo.syslogins ......
47    **	the code should look like:
48    **	1. Now, the SQL statement:
49    **		insert master.dbo.syslogins ......
50    **	2. Add a HA synchronization section right after the SQL statement:
51    **		
52    **
53    **	You may need to do similar change for each built-in function you
54    **	want to add.
55    */
56    
57    create procedure sp_maplogin
58        @authmethod varchar(30) = NULL, /* Authentication mechanism */
59        @externname varchar(255) = NULL, /* client user name */
60        @loginame varchar(255) = NULL /* user's local name */
61    AS
62        BEGIN
63    
64            DECLARE @msg varchar(1024),
65                @authid int,
66                @any_authid int, /* LOGIN_ANY auth id */
67                @syslog_authid int, /* syslogin auth id */
68                @syslog_authmch varchar(30), /* syslogin auth mech name */
69                @suid int,
70                @login_class smallint, /* omni's attribute  class */
71                @attrib smallint, /* attr. id for ext. login */
72                @action smallint,
73                @dummy int,
74                @HA_CERTIFIED tinyint, /* Is the SP HA certified ? */
75                @retstat int,
76                @config int,
77                @del int,
78                @auth_mech varchar(30),
79                @client_name varchar(255),
80                @login_name varchar(255),
81                @dbname varchar(255), /* for logexec error message */
82                @master_is_rep int /* whether master db is replicated */
83    
84            /*
85            ** Only a user with sso_role can add extern login mappings
86            */
87            if (proc_role("sso_role") < 1)
88                return 1
89    
90            select @HA_CERTIFIED = 0
91            select @retstat = 0
92    
93    
94    
95            /* check to see if we are using HA specific SP for a HA enabled server */
96            exec @retstat = sp_ha_check_certified 'sp_maplogin', @HA_CERTIFIED
97            if (@retstat != 0)
98                return (1)
99    
100           /*
101           ** If we are logging this system procedure for replication,
102           ** we must be in the 'master' database to avoid creating a
103           ** multi-database transaction which could make recovery of
104           ** the 'master' database impossible.
105           */
106           select @master_is_rep = getdbrepstat(1)
107   
108           if (@master_is_rep < 0)
109           begin
110               /*
111               ** 18409, "The built-in function getdbrepstat() failed."
112               */
113               raiserror 18409, "getdbrepstat"
114               return (1)
115           end
116   
117           select @dbname = db_name()
118   
119           if (@master_is_rep > 0) and (@dbname != "master")
120           begin
121               /*
122               ** 18388, "You must be in the master database in order
123               ** to run '%1!'."
124               */
125               raiserror 18388, "sp_maplogin"
126               return (1)
127           end
128   
129           /*
130           **  If we're in a transaction, disallow this since it might make recovery
131           **  impossible.
132           */
133           if @@trancount > 0
134           BEGIN
135               /*		
136               ** 17260 Can't run '%1!' from within a transaction.
137               */
138               raiserror 17260, "sp_maplogin"
139               return 1
140           END
141   
142           /* 
143           ** We cannot define any mapping for all authentications
144           ** and all logins
145           */
146           if ((@authmethod is null or upper(@authmethod) = 'ANY')
147                   and (@externname is null or upper(@externname) = 'ANY'))
148           BEGIN
149               /*		
150               ** 19453  "Cannot define a mapping for ALL authentications 
151               ** and ALL logins -- map request denied.
152               */
153               raiserror 19453
154               return 1
155           END
156   
157           /*
158           ** Check that the auth method is valid. NULL means ALL.
159           */
160           if (@authmethod is null)
161               select @authmethod = 'ANY'
162   
163           /*
164           ** Check whether authentication mechanism specified is valid or not.
165           ** 'AUTH_DEFAULT' and 'AUTH_MASK' are new values added in spt_values
166           ** used to obtain value of default ('ANY') authmech or authentication
167           ** mask respectively. They are not valid names that the user can
168           ** specify as authentication mechanism.
169           */
170           select @authid = low, @config = number
171           from master.dbo.spt_values
172           where type = 'ua' and upper(name) = upper(@authmethod)
173               and upper(name) not in ('AUTH_DEFAULT', 'AUTH_MASK')
174   
175           if @@rowcount = 0
176           BEGIN
177               /*		
178               ** 19257  "The authentication mechanism '%1!' is not valid .
179               */
180               raiserror 19257, @authmethod
181               return (1)
182           END
183   
184           /*
185           ** Check that the authentication method is enabled. The configuration option
186           ** is in spt_values.number.
187           ** For SMP or SDC, look up syscurconfigs for local instance.
188           */
189           if (@config != 0) and not exists (select 1
190                   from master.dbo.syscurconfigs a
191   
192                   where a.config = @config and a.value != 0)
193   
194           BEGIN
195               /*
196               ** 19259, "Warning. Authentication mechanism '%1!' is not enabled."
197               */
198               exec sp_getmessage 19259, @msg output
199               print @msg, @authmethod
200           END
201   
202           select @del = 0
203   
204           /*
205           ** Check the login name/action
206           */
207           if upper(@loginame) = 'CREATE LOGIN'
208               select @suid = - 3
209           else if (upper(@loginame) = 'DROP')
210               select @del = 1
211           else
212           BEGIN
213               /*
214               ** Check that the @loginame is valid.
215               */
216               /*
217               **  Set a mask with all the authentication bits using
218               ** 'AUTH_MASK'
219               */
220               select @any_authid = low
221               from master.dbo.spt_values
222               where type = 'ua' and upper(name) = 'AUTH_MASK'
223   
224               select @suid = suid, @syslog_authid = (status & @any_authid)
225               from master.dbo.syslogins
226               where name = @loginame
227                   and ((status & 512) != 512) /* not LOGIN PROFILE */
228               if @@rowcount = 0
229               BEGIN
230                   /*		
231                   ** 18294 "User '%1!' is not a local user -- 
232                   ** request denied."
233                   */
234                   raiserror 18294, @loginame
235                   return (1)
236               END
237   
238               /* authid of 0 means ANY, set it the local var to this value. */
239               if @syslog_authid = 0
240                   select @syslog_authid = @any_authid
241   
242               /*
243               **  Check the authentication mechanism for a login and authentication
244               **  mechanism parameter to sp_maplogin do not conflict.  There should
245               **  be at least one bit matching in the two masks representing the
246               **  authentication mechanism.
247               **
248               **  The bitmask for auth mech NONE/NULL has already been mapped to ANY.
249               */
250   
251               if (@syslog_authid & @authid) = 0
252               BEGIN
253                   select @syslog_authmch = name
254                   from master.dbo.spt_values
255                   where type = 'ua' and low = @syslog_authid
256                       and upper(name) not in ('AUTH_DEFAULT',
257                           'AUTH_MASK')
258                   /*		
259                   ** 19447 "User '%1!' allows only '%2!' authentication 
260                   ** mechanism to be used -- request denied."
261                   */
262                   raiserror 19447, @loginame, @syslog_authmch
263                   return (1)
264               END
265           END
266   
267           if (@externname is null or upper(@externname) = 'ANY')
268           BEGIN
269               select @externname = '*'
270           END
271   
272           if (@externname != '*' and @del = 0)
273           BEGIN
274               /*
275               **  Check that an explicit value of @externname is not already a local login
276               **  or login profile
277               */
278               if exists (select 1
279                       from master.dbo.syslogins
280                       where name = @externname)
281               BEGIN
282                   /*		
283                   ** 19445 "External name '%1!' is already a local 
284                   ** login -- map request denied."
285                   */
286                   raiserror 19445, @externname
287                   return (1)
288               END
289           END
290           /*
291           ** Check if the ASE authentication mechanism is used for the mapping.
292           ** New behavior in ASE 12.5.4 prevents local logins from being mapped
293           ** to other local logins, making most actions with ASE auth mech invalid.
294           ** The only allowed action allowed for ASE is 'drop', to aid in removing any
295           ** mappings that may have been added in earlier releases.
296           */
297           if (upper(@authmethod) = "ASE") and (@del = 0)
298           BEGIN
299               /*		
300               ** 19450  "A mapping with authentication mechanism '%1!' is
301               ** not allowed, only action 'drop' is permitted."
302               */
303               raiserror 19450, @authmethod
304               return (1)
305           END
306           /*
307           ** The mapping is stored in sysattributes. The entries for external
308           ** authentication mechanisms are as follows:
309           **
310           **	- class:	20
311           **	- attribute:	0
312           **	- object:	mapped suid
313           **			- It may have a real suid or,
314           **			- INVALID_SUID (-2), to map using the external name.
315           **			- CRTLOGIN_SUID (-3), to create login if it does not
316           **			  exist.
317           **	- object_cinfo:	external name, or '*' for all external names.
318           **	- object_info1: authentication mechanism. If we map any authentication
319           **			it will contain LOGIN_ALL, that is an OR of all the
320           **			existing authentication mechinsms.
321           **
322           ** If there is already an entry for that external user, we'll update
323           ** it, else we'll insert a new row.
324           ** For each user only one authentication mechanism is allowed. However,
325           ** when setting a generic map (extern user name is null), there can
326           ** be multiple entries for it. We can specify that all the users using
327           ** PAM will be mapped as u1, all users using LDAP will be mapped
328           ** u2, etc.
329           */
330           select @login_class = 20, @attrib = 0
331   
332           /*
333           ** Check whether a mapping already exists. If it does, update it
334           ** or delete it, depending on the parameter @delete.
335           ** If the client user name is null, we will look for a mapping for
336           ** all users with the authentication method specified.
337           ** If the client user name is not null, we will look for a mapping
338           ** for this user.
339           */
340           if ((@externname = '*' and
341                       exists (select * from master.dbo.sysattributes where
342                               class = @login_class and attribute = @attrib and
343                               object_cinfo = '*' and
344                               object_info1 = @authid))
345                   or (@externname != '*' and
346                       exists (select * from master.dbo.sysattributes where
347                               class = @login_class and attribute = @attrib and
348                               object_cinfo = @externname)))
349           BEGIN
350               if (@del = 0)
351                   select @action = 2 /* update attribute */
352               else
353                   select @action = 3 /* delete attribute */
354           END
355           else
356           BEGIN
357               if (@del = 0)
358                   select @action = 1 /* insert attribute */
359               else
360                   /* Nothing to delete. */
361                   return (0)
362           END
363   
364           /*
365           ** First validate the row. 
366           */
367           if attrib_valid(@login_class, @attrib, "LM", @suid, @authid, NULL, NULL,
368                   @externname, NULL, NULL, NULL, NULL, NULL, @action) = 0
369           BEGIN
370               return (1)
371           END
372   
373           /* 
374           ** This transaction also writes a log record for replicating the
375           ** invocation of this procedure. If logexec() fails, the transaction
376           ** is aborted.
377           **
378           ** IMPORTANT: The name rs_logexec is significant and is used by
379           ** Adaptive Server.
380           */
381           begin tran rs_logexec
382   
383   
384   
385           /*
386           ** Now insert/update/delete the row
387           */
388           if @action = 1
389           BEGIN
390               insert into master.dbo.sysattributes(class, attribute,
391                   object_type, object_info1, object, object_cinfo,
392                   image_value, object_info2)
393               values (@login_class, @attrib, "LM", @authid, @suid,
394                   @externname, null, null)
395   
396               if (@@error != 0)
397                   goto clean_all
398   
399               /*
400               ** 19256 "Client authentication mapping updated."
401               */
402               exec sp_getmessage 19256, @msg output
403               print @msg
404           END
405           else if @action = 2
406           BEGIN
407               if (@externname = '*')
408               BEGIN
409                   /* 
410                   ** Select the previous mapping information to be 
411                   ** displayed in the message before updating the row.
412                   */
413                   select @auth_mech = isnull(s.name, "ANY"),
414                       @client_name =
415                       case object_cinfo
416                           when '*' then "ANY"
417                           else object_cinfo
418                       end,
419                       @login_name =
420                       case object
421                           when - 2 then "ANY"
422                           when - 3 then "CREATE LOGIN"
423                           else isnull(suser_name(object), "NO MAP")
424                       end
425                   from master.dbo.sysattributes, master.dbo.spt_values s
426                   where class = @login_class and attribute = @attrib and
427                       (object_info1 = s.low) and
428                       (s.name not in ('AUTH_MASK')) and
429                       (s.type = 'ua') and
430                       object_cinfo = '*' and object_info1 = @authid
431   
432                   update master.dbo.sysattributes
433                   set object = @suid
434                   where class = @login_class and attribute = @attrib and
435                       object_cinfo = '*' and
436                       object_info1 = @authid
437               END
438               else
439               BEGIN
440                   /*
441                   ** Select the previous mapping information to be
442                   ** displayed in the message before updating the row.
443                   */
444                   select @auth_mech = isnull(s.name, "ANY"),
445                       @client_name =
446                       case object_cinfo
447                           when '*' then "ANY"
448                           else object_cinfo
449                       end,
450                       @login_name =
451                       case object
452                           when - 2 then "ANY"
453                           when - 3 then "CREATE LOGIN"
454                           else isnull(suser_name(object), "NO MAP")
455                       end
456                   from master.dbo.sysattributes, master.dbo.spt_values s
457                   where class = @login_class and attribute = @attrib and
458                       (object_info1 = s.low) and
459                       (s.name not in ('AUTH_MASK')) and
460                       object_cinfo = @externname
461   
462                   update master.dbo.sysattributes
463                   set object = @suid, object_info1 = @authid
464                   where class = @login_class and
465                       attribute = @attrib and
466                       object_cinfo = @externname
467               END
468   
469               if (@@error != 0)
470                   goto clean_all
471   
472               /*
473               ** 19940 "Client authentication mapping overwritten.
474               ** Previous values were @authentication_mech='%1!',
475               ** @client_name='%2!' and @login_name='%3!'."
476               */
477               exec sp_getmessage 19940, @msg output
478               print @msg, @auth_mech, @client_name, @login_name
479           END
480           else if @action = 3
481           BEGIN
482               delete master.dbo.sysattributes
483               where class = @login_class and
484                   attribute = @attrib and
485                   object_cinfo = @externname and
486                   object_info1 = @authid
487               if (@@error != 0)
488                   goto clean_all
489   
490               /*
491               ** 19256 "Client authentication mapping updated."
492               */
493               exec sp_getmessage 19256, @msg output
494               print @msg
495           END
496   
497   
498   
499           /*
500           ** Sync the in-memory RDES with the new values
501           ** in sysattributes.
502           */
503           if attrib_notify(@login_class, @attrib, "LM", @suid, @authid, NULL,
504                   NULL, NULL, NULL, NULL, NULL, NULL, NULL,
505                   @action) = 0
506               goto clean_all
507   
508           /*
509           ** log the command for possible replication
510           */
511           if (@master_is_rep > 0)
512           begin
513               if (logexec(1) != 1)
514               begin
515                   /*
516                   ** , "17869 Stored procedure %1 failed'
517                   **       because '%2' failed in database '%3'."
518                   */
519                   raiserror 17869, "sp_maplogin", "logexec()", @dbname
520                   goto clean_all
521               end
522           end
523   
524           commit tran rs_logexec
525   
526           return (@retstat)
527       END
528   
529   clean_all:
530       rollback tran rs_logexec
531       return (1)
532   


exec sp_procxmode 'sp_maplogin', 'AnyMode'
go

Grant Execute on sp_maplogin to public
go
DEFECTS
 MINU 4 Unique Index with nullable columns master..sysattributes master..sysattributes
 QPUI 4 Join or Sarg with Un-Rooted Partial Index Use SARG Candidate index: spt_values.spt_valuesclust clustered
(number, type)
Intersection: {type}
172
 QPUI 4 Join or Sarg with Un-Rooted Partial Index Use SARG Candidate index: spt_values.spt_valuesclust clustered
(number, type)
Intersection: {type}
222
 QPUI 4 Join or Sarg with Un-Rooted Partial Index Use SARG Candidate index: spt_values.spt_valuesclust clustered
(number, type)
Intersection: {type}
255
 QPUI 4 Join or Sarg with Un-Rooted Partial Index Use JOIN Candidate index: sysattributes.csysattributes unique clustered
(class, attribute, object_type, object, object_info1, object_info2, object_info3, object_cinfo)
Intersection: {object_info1}
Uncovered: [object_type, object, object_info2, object_info3]
427
 QPUI 4 Join or Sarg with Un-Rooted Partial Index Use SARG Candidate index: spt_values.spt_valuesclust clustered
(number, type)
Intersection: {type}
428
 QPUI 4 Join or Sarg with Un-Rooted Partial Index Use JOIN Candidate index: sysattributes.csysattributes unique clustered
(class, attribute, object_type, object, object_info1, object_info2, object_info3, object_cinfo)
Intersection: {object_info1}
Uncovered: [object_type, object, object_info2, object_info3]
458
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 192
 TNOI 4 Table with no index master..syscurconfigs master..syscurconfigs
 TNOU 4 Table with no unique index master..spt_values master..spt_values
 MGTP 3 Grant to public master..spt_values  
 MGTP 3 Grant to public master..sysattributes  
 MGTP 3 Grant to public master..syscurconfigs  
 MGTP 3 Grant to public master..syslogins  
 MGTP 3 Grant to public sybsystemprocs..sp_maplogin  
 MNER 3 No Error Check should check return value of exec 198
 MNER 3 No Error Check should check return value of exec 402
 MNER 3 No Error Check should check @@error after update 432
 MNER 3 No Error Check should check @@error after update 462
 MNER 3 No Error Check should check return value of exec 477
 MNER 3 No Error Check should check return value of exec 493
 MUCO 3 Useless Code Useless Begin-End Pair 62
 MUCO 3 Useless Code Useless Brackets 87
 MUCO 3 Useless Code Useless Brackets 97
 MUCO 3 Useless Code Useless Brackets 98
 MUCO 3 Useless Code Useless Brackets 108
 MUCO 3 Useless Code Useless Brackets 114
 MUCO 3 Useless Code Useless Brackets 126
 MUCO 3 Useless Code Useless Brackets 146
 MUCO 3 Useless Code Useless Brackets 160
 MUCO 3 Useless Code Useless Brackets 181
 MUCO 3 Useless Code Useless Brackets 209
 MUCO 3 Useless Code Useless Brackets 235
 MUCO 3 Useless Code Useless Brackets 263
 MUCO 3 Useless Code Useless Brackets 267
 MUCO 3 Useless Code Useless Brackets 272
 MUCO 3 Useless Code Useless Brackets 287
 MUCO 3 Useless Code Useless Brackets 304
 MUCO 3 Useless Code Useless Brackets 340
 MUCO 3 Useless Code Useless Brackets 350
 MUCO 3 Useless Code Useless Brackets 357
 MUCO 3 Useless Code Useless Brackets 361
 MUCO 3 Useless Code Useless Brackets 370
 MUCO 3 Useless Code Useless Brackets 396
 MUCO 3 Useless Code Useless Brackets 407
 MUCO 3 Useless Code Useless Brackets 469
 MUCO 3 Useless Code Useless Brackets 487
 MUCO 3 Useless Code Useless Brackets 511
 MUCO 3 Useless Code Useless Brackets 513
 MUCO 3 Useless Code Useless Brackets 526
 MUCO 3 Useless Code Useless Brackets 531
 MUPK 3 Update column which is part of a PK or unique index object 433
 MUPK 3 Update column which is part of a PK or unique index object 463
 QAFM 3 Var Assignment from potentially many rows 170
 QAFM 3 Var Assignment from potentially many rows 220
 QAFM 3 Var Assignment from potentially many rows 253
 QAFM 3 Var Assignment from potentially many rows 413
 QAFM 3 Var Assignment from potentially many rows 444
 QIWC 3 Insert with not all columns specified missing 7 columns out of 15 390
 QNAJ 3 Not using ANSI Inner Join 425
 QNAJ 3 Not using ANSI Inner Join 456
 QNUA 3 Should use Alias: Column object_cinfo should use alias sysattributes 415
 QNUA 3 Should use Alias: Column object_cinfo should use alias sysattributes 417
 QNUA 3 Should use Alias: Column object should use alias sysattributes 420
 QNUA 3 Should use Alias: Column object should use alias sysattributes 423
 QNUA 3 Should use Alias: Table master..sysattributes 425
 QNUA 3 Should use Alias: Column attribute should use alias sysattributes 426
 QNUA 3 Should use Alias: Column class should use alias sysattributes 426
 QNUA 3 Should use Alias: Column object_info1 should use alias sysattributes 427
 QNUA 3 Should use Alias: Column object_cinfo should use alias sysattributes 430
 QNUA 3 Should use Alias: Column object_info1 should use alias sysattributes 430
 QNUA 3 Should use Alias: Column object_cinfo should use alias sysattributes 446
 QNUA 3 Should use Alias: Column object_cinfo should use alias sysattributes 448
 QNUA 3 Should use Alias: Column object should use alias sysattributes 451
 QNUA 3 Should use Alias: Column object should use alias sysattributes 454
 QNUA 3 Should use Alias: Table master..sysattributes 456
 QNUA 3 Should use Alias: Column attribute should use alias sysattributes 457
 QNUA 3 Should use Alias: Column class should use alias sysattributes 457
 QNUA 3 Should use Alias: Column object_info1 should use alias sysattributes 458
 QNUA 3 Should use Alias: Column object_cinfo should use alias sysattributes 460
 QPRI 3 Join or Sarg with Rooted Partial Index Use SARG Candidate index: sysattributes.csysattributes unique clustered
(class, attribute, object_type, object, object_info1, object_info2, object_info3, object_cinfo)
Intersection: {object_info1, object_cinfo, attribute, class}
342
 QPRI 3 Join or Sarg with Rooted Partial Index Use SARG Candidate index: sysattributes.csysattributes unique clustered
(class, attribute, object_type, object, object_info1, object_info2, object_info3, object_cinfo)
Intersection: {class, attribute, object_cinfo}
347
 QPRI 3 Join or Sarg with Rooted Partial Index Use SARG Candidate index: sysattributes.csysattributes unique clustered
(class, attribute, object_type, object, object_info1, object_info2, object_info3, object_cinfo)
Intersection: {object_info1, object_cinfo, attribute, class}
434
 QPRI 3 Join or Sarg with Rooted Partial Index Use SARG Candidate index: sysattributes.csysattributes unique clustered
(class, attribute, object_type, object, object_info1, object_info2, object_info3, object_cinfo)
Intersection: {class, attribute, object_cinfo}
464
 QPRI 3 Join or Sarg with Rooted Partial Index Use SARG Candidate index: sysattributes.csysattributes unique clustered
(class, attribute, object_type, object, object_info1, object_info2, object_info3, object_cinfo)
Intersection: {object_info1, object_cinfo, attribute, class}
483
 QSWV 3 Sarg with variable @syslog_authid, Candidate Index: spt_values.spt_valuesclust clustered(number, type) U 255
 VUNU 3 Variable is not used @dummy 73
 MSUB 2 Subquery Marker 189
 MSUB 2 Subquery Marker 278
 MSUB 2 Subquery Marker 341
 MSUB 2 Subquery Marker 346
 MTR1 2 Metrics: Comments Ratio Comments: 51% 57
 MTR2 2 Metrics: Cyclomatic Complexity Cyclo: 55 = 65dec - 12exi + 2 57
 MTR3 2 Metrics: Query Complexity Complexity: 203 57
 PRED_QUERY_COLLECTION 2 {a=master..sysattributes, sv=master..spt_values} 0 413
 PRED_QUERY_COLLECTION 2 {a=master..sysattributes, sv=master..spt_values} 0 444

DEPENDENCIES
PROCS AND TABLES USED
reads table master..syslogins (1)  
reads table master..syscurconfigs (1)  
calls proc sybsystemprocs..sp_getmessage  
   calls proc sybsystemprocs..sp_validlang  
      reads table master..syslanguages (1)  
   reads table master..syslanguages (1)  
   reads table sybsystemprocs..sysusermessages  
   reads table master..sysmessages (1)  
read_writes table master..sysattributes (1)  
reads table master..spt_values (1)  
calls proc sybsystemprocs..sp_ha_check_certified  
   reads table tempdb..sysobjects (1)