DatabaseProcApplicationCreatedLinks
sybsystemprocssp_replication_path  31 Aug 14Defects Dependencies

1     
2     /*
3     **  Messages for "sp_replication_path"
4     **
5     ** 11220, "Parameter cannot be NULL."
6     ** 17067 "Unable to encrypt password for '%1!'. See prior error message 
7     **	 for reason."
8     ** 17260, "Can't run %1! from within a transaction."
9     ** 17421, "No such database -- run sp_helpdb to list databases."
10    ** 17756, "The execution of the stored procedure '%1!' in database
11    **	  '%2!' was aborted because there was an error in writing the
12    **	  replication log record."
13    ** 18102, Table '%1!' does not exist in this database.
14    ** 18107, Stored procedure '%1!' does not exist in this database.
15    ** 18118, Object '%1!' does not exist in this database.
16    ** 18375, "You are not authorized to execute this stored procedure. Only the 
17    **	  System Administrator (SA), the Database Owner (DBO) or a user with 
18    **	  replication_role authorization can execute this stored procedure."
19    ** 18408, "The stored procedure must be executed with the name of the
20    **	  current database."
21    ** 18409, "The built-in function '%1!' failed. Please see any other messages 
22    **	  printed along with this message."
23    ** 18481, '%1!' is an invalid configuration parameter.
24    ** 19213, "Invalid argument or unsupported command: %1!."
25    ** 19384, The '%1!' parameter is required with '%2!' parameter.
26    ** 19415, The '%1!' parameter is required for the '%2!' command.
27    ** 19805, An unexpected syntax error has occurred.
28    ** 19859, Argument '%1!' is not valid for '%2!'.
29    **
30    */
31    create procedure sp_replication_path
32        @dbname varchar(30), /* always database name	     */
33        @action varchar(30) = NULL, /* add|drop|config|bind|unbind|list */
34        /*
35        ** sp_replication_path has an additional four positional parameters the
36        ** specific usage of these parameters is dictated by the syntax of the
37        ** action; so, rather than give a name that is meaningful in some context
38        ** but misleading in others, the anonymous '@p...' names are used
39        */
40        @p1 varchar(255) = NULL,
41        @p2 varchar(1023) = NULL, /* must be able to hold long names
42        **  of the form site.db.owner.name */
43        @p3 varchar(1023) = NULL, /* must be able to hold long names
44        **  of the form site.db.owner.name */
45        @p4 varchar(255) = NULL,
46        @rs_encpwd varbinary(256) = NULL /* encrypted rs password, 
47    				     ** internal use for replication.
48    				     */
49    as
50    
51        declare @status int, /* Local status			*/
52            @retval int, /* Return status 		*/
53            @has_sa_role int,
54            @has_repl_role int,
55            @owner varchar(255), /* Owner of the object 	     	*/
56            @db varchar(255), /* Db name 	 	     	*/
57            @dbid int, /* Db id			*/
58            @dbuid int, /* Db's owner id		*/
59            @blt_failure int, /* builting failure		*/
60            @rep_constant int, /* Indicate a replicated object */
61            @rep_all int, /* DB's replication constant 	*/
62            @rep_l1 int, /* DB's replication constant	*/
63            @report varchar(255) /* Report string for successful **
64        ** actions (will be filled in   **
65        ** in the individual sections)	*/
66    
67        declare @MRP_CLASS int /* MRP_CLASS constant		*/
68        select @MRP_CLASS = 41
69    
70        declare @STATIC_KEY int /* for rs password encryption */
71        select @STATIC_KEY = 54
72    
73    
74        if @@trancount > 0
75        begin
76            /* 
77            ** 17260, "Can't run %1! from within a transaction."
78            */
79            raiserror 17260, "sp_relication_path"
80            return (1)
81        end
82    
83        /*
84        ** if the dbname was not supplied, or the dbname is "help" and
85        ** no action parameter was supplied then we jump to the syntax help
86        */
87        if ((@dbname is NULL) or
88                (@dbname = "help" and @action is NULL))
89        begin
90            goto usage
91        end
92    
93        set chained off
94        set transaction isolation level 1
95    
96        /* Init variables */
97        select @blt_failure = - 2, /* LT_REP_GET_FAILED */
98            @rep_all = 2048, /* LT_REP_ALL */
99            @rep_l1 = 4096, /* LT_REP_L1 */
100           @rep_constant = - 32768,
101           @report = NULL
102   
103   
104       /* Get the database owner */
105       select @dbuid = suid, @dbid = dbid
106       from master.dbo.sysdatabases
107       where name = @dbname
108   
109       if (@dbid is null)
110       begin
111           /*
112           ** 17421, "No such database -- run sp_helpdb to display databases."
113           */
114           raiserror 17421
115           return (1)
116       end
117   
118       /*
119       ** Check SA and REPLICATION role.
120       ** Keep their status in local variables for auditing later.
121       */
122       select @has_sa_role = charindex("sa_role", show_role())
123       select @has_repl_role = charindex("replication_role", show_role())
124   
125       /*
126       **  Only the Database Owner (DBO) or
127       **  Accounts with SA role or replication role can execute it.
128       **  First check if we are the DBO if the database name is specified.
129       */
130       if (suser_id() != @dbuid)
131       begin
132           /* Check if we have sa_role or replication_role. */
133           if (@has_sa_role = 0 and @has_repl_role = 0)
134           begin
135               /* Audit authorization failure */
136               select @retval = proc_role("sa_role")
137               select @retval = proc_role("replication_role")
138   
139               /*
140               **  18375, "You are not authorized to execute this stored
141               ** procedure. Only the System Administrator (SA), the
142               ** Database Owner (DBO) or a user with replication_role
143               ** authorization can execute this stored procedure."
144               */
145               raiserror 18375
146               return (1)
147           end
148       end
149   
150       /* Audit authorization succeeded */
151       if (@has_sa_role > 0)
152           select @retval = proc_role("sa_role")
153       if (@has_repl_role > 0)
154           select @retval = proc_role("replication_role")
155   
156   
157       /*
158       ** Make sure that the database is the current database.
159       */
160       if (@dbname != db_name())
161       begin
162           /*
163           ** 18408, "The stored procedure must be executed with the name of the
164           **	   current database."
165           */
166           raiserror 18408
167           return (1)
168       end
169   
170       /* 
171       ** Check first if the action syntax is correct 
172       */
173       select @action = lower(@action)
174       if (@action is null or @action not in ('add', 'drop', 'config',
175                   'bind', 'unbind', 'list'))
176       begin
177           if (@action != "help")
178           begin
179               raiserror 19213, @action
180           end
181           goto usage
182       end
183   
184   
185       /*
186       ** action is 'list' so we will do the work here without the builtin
187       */
188       if (@action = 'list')
189       begin
190           /*
191           ** Display information about the MRP environment. With no parameters
192           ** show everything organized by path. If a single parameter is given 
193           ** it must be one of the supported types (currently path and table|
194           ** sproc objects); information will be organized by the specified type
195           ** If the second parameter is supplied its type must match the given
196           ** type in the first parameter; detailed information about the given
197           ** object will be provided.
198           **
199           ** Note: 'list' does not require a call to the built-in
200           **
201           **  Var.  
202           ** -----  -------------------------------------
203           **  @p1   type to display (optional)
204           **        must be valid type (path|table|sproc)
205           **  @p2   name of object to display (optional)
206           **        name must exist and agree with type
207           **  @p3	  unused
208           **  @p4   unused
209           **
210           ** Errors raised by 'list'
211           **
212           **	error	 description
213           **	-----	-------------------------------------------------------
214           **	18102	Table '%1!' does not exist in this database.
215           **	18107	Stored procedure '%1!' does not exist in this database.
216           **	18118	Object '%1!' does not exist in this database.
217           **	19805	An unexpected syntax error has occurred.
218           **	19859	Argument '%1!' is not valid for '%2!'.
219           **	
220           */
221   
222           /*
223           ** There are two basic ways we can look at the MRP data; from either
224           ** an binding- or path-centric view (axis). 
225           ** For a binding-centric view (default) we start with the list of bound
226           ** objects and display the path(s) to which each is bound. Searches on
227           ** the binding axis need a further qualifier to indicate what type of
228           ** object we are looking for (i.e. table, sproc, etc.)
229           **
230           ** For a path-centric view the list is built upon the set of paths and
231           ** objects bound to each path are displayed.
232           **
233           ** Both binding and path axis searches may be further restricted by
234           ** name.
235           **
236           ** The search_omin/omax are used to limit searches on the underlying
237           ** layer once we have acquired an object id. Searches on these values
238           ** are always search_omin <=  <= search_omax. There are only
239           ** two choices for the values to be set to:
240           **  - search_omin = 1, search_omax = MAXINT indicates a wildcard
241           **    search that will match all valid values for object ids, we are
242           **    looking for all instances of a broader search type
243           **  - search_omin = search_omax =  indicates that we are
244           **    seeking a specific object/path instance
245           */
246           declare @search_axis varchar(255) /* path or binding search axis     */
247           declare @search_qual varchar(255) /* limits binding search to a type */
248           declare @search_name varchar(255) /* object/path name to search on   */
249           declare @search_omin int /* object id search minimum value  */
250           declare @search_omax int /* object id search maximum value  */
251   
252           declare @lpath_id int /* logical path id 		*/
253           declare @lpath_name varchar(255) /* logical path name 		*/
254           declare @ppath_id int /* physical path id 		*/
255           declare @ppath_name varchar(255) /* physical path name 		*/
256           declare @rs_id int /* RS definition id 		*/
257           declare @rs_name varchar(255) /* RS definition name 		*/
258           declare @bnd_obj int /* bound object id		*/
259           declare @obj_name varchar(255) /* bound object name		*/
260           declare @atype char(2) /* object attribute type	*/
261   
262           /*
263           ** by default we cast a wide net across the object bindings, we'll pare
264           ** these terms down if search restrictions are applied
265           */
266           select @search_axis = "all"
267           select @search_qual = '%'
268           select @search_name = '%'
269           select @search_omin = 1
270           select @search_omax = 2147483647
271   
272           /*
273           ** 'list' never uses @p3 or @p4 or @rs_encpwd
274           */
275           if ((@p3 is not NULL) or (@p4 is not NULL) or (@rs_encpwd is not NULL))
276           begin
277               /*
278               ** 19805
279               ** An unexpected syntax error has occured.
280               */
281               raiserror 19805
282               goto done
283           end
284   
285           /*
286           ** set up the search arguments
287           */
288           if (@p1 is NOT NULL)
289           begin
290               if (@p1 = "all")
291               begin
292                   select @search_axis = "all"
293                   if (@p2 is not NULL)
294                   begin
295                       /*
296                       ** 19859 
297                       ** Argument '%1!' is not valid for '%2!'.
298                       */
299                       raiserror 19859, @p2, "all"
300                       goto done
301                   end
302               end
303               else if (@p1 = "path")
304               begin
305                   select @search_axis = "path"
306                   if (@p2 is NOT NULL)
307                   begin
308                       if exists (select 1 from sysattributes where
309                                   class = @MRP_CLASS and
310                                   attribute = 22 and
311                                   char_value = @p2)
312                       begin
313                           select @search_name = @p2
314                       end
315                       else
316                       begin
317                           /*
318                           ** 18118
319                           ** Object '%1!' does not exist in this database.
320                           */
321                           raiserror 18118, @p2
322                           return (1)
323                       end
324                   end
325                   else
326                   begin
327                       select @search_name = '%'
328                   end
329               end
330               else
331               begin
332                   /*
333                   ** the search_axis is binding, set the
334                   **  qualifier and limit to wildcard
335                   */
336                   select @search_axis = "binding"
337                   select @search_qual = '%'
338                   select @search_omin = 1
339                   select @search_omax = 2147483647
340                   if (@p1 is NOT NULL)
341                   begin
342                       /*
343                       ** lets make sure we have a qualified type 
344                       */
345                       if (lower(@p1) = "table")
346                       begin
347                           select @search_qual = "T "
348                       end
349                       else if (lower(@p1) = "sproc")
350                       begin
351                           select @search_qual = "P "
352                       end
353                       else
354                       begin
355                           print "Unknown type %1!", @p1
356                           return 1
357                       end
358   
359                       /*
360                       ** if we are looking for a specific object
361                       **  grab the name for the search limit
362                       */
363                       if (@p2 is NOT NULL)
364                       begin
365                           select @bnd_obj = object_id(@p2)
366                           if (@bnd_obj is NULL)
367                           begin
368                               if (@search_qual = "T ")
369                               begin
370                                   /*
371                                   ** 18102
372                                   ** Table '%1!' does not exist
373                                   ** in this database.
374                                   */
375                                   raiserror 18102, @p2
376                               end
377                               else if (@search_qual = "P ")
378                               begin
379                                   select @bnd_obj =
380                                       object_id("sybsystemprocs.." + @p2)
381                                   if (@bnd_obj is NULL)
382                                   begin
383                                       /*
384                                       ** 18107
385                                       ** Stored procedure '%1!' 
386                                       ** does not exist in this
387                                       ** database.
388                                       */
389                                       raiserror 18107, @p2
390                                   end
391                                   else
392                                   begin
393                                       /*
394                                       ** found a system sproc
395                                       ** we have to jump past
396                                       ** the return
397                                       */
398                                       goto set_limits
399                                   end
400                               end
401                               else
402                               begin
403                                   /*
404                                   ** 18118
405                                   ** Object '%1!' does not exist
406                                   ** in this database.
407                                   */
408                                   raiserror 18118, @p2
409                               end
410                               return 1
411                           end
412                           else
413                           begin
414                               /*
415                               ** Ensure that the found object is of 
416                               ** the desired type
417                               */
418                               if ((@search_qual = "T ") and
419                                           (select count(*) from sysobjects where
420                                               name = @p2 and
421                                               type = "U") = 0)
422                               begin
423                                   /*
424                                   ** 18102
425                                   ** Table '%1!' does not exist
426                                   ** in this database.
427                                   */
428                                   raiserror 18102, @p2
429                                   return (1)
430                               end
431                               else if ((@search_qual = "P ") and
432                                           (select count(*) from sysobjects where
433                                               name = @p2 and
434                                               type = "P") = 0)
435                               begin
436                                   /*
437                                   ** 18107
438                                   ** Stored procedure '%1!' 
439                                   ** does not exist in this
440                                   ** database.
441                                   */
442                                   raiserror 18107, @p2
443                                   return (1)
444                               end
445                           end
446                           /*
447                           ** set the object limits to the object
448                           ** id so we only find the matching object
449                           ** when we search
450                           */
451   set_limits: select @search_omin = @bnd_obj
452                           select @search_omax = @bnd_obj
453                       end
454                   end
455               end
456           end
457   
458           /*
459           ** if the search_axis is binding (or all) we'll get the MRP
460           ** information from an object perspective
461           */
462           if (@search_axis = "binding" OR @search_axis = "all")
463           begin
464               /*
465               ** The first level cursor gets the object id and type, and 
466               ** the path id to which the object is bound for each matching
467               ** object in the database
468               */
469               declare binding_for_obj_id_cur cursor
470               for select object, object_type, object_info1 from sysattributes
471               where class = @MRP_CLASS and attribute = 23
472                   and object_type like @search_qual
473                   and (object >= @search_omin and object <= @search_omax)
474               for read only
475   
476               create table #paths_for_bindings(Binding varchar(255),
477                   Type char(2),
478                   Path varchar(255))
479               open binding_for_obj_id_cur
480               while (1 = 1)
481               begin
482                   select @bnd_obj = 0
483                   select @obj_name = NULL
484                   select @lpath_id = 0
485                   select @lpath_name = NULL
486                   select @atype = NULL
487   
488                   fetch binding_for_obj_id_cur into
489                       @bnd_obj, @atype, @lpath_id
490   
491                   if (@@sqlstatus != 0)
492                   begin
493                       break
494                   end
495   
496                   /*
497                   ** locate the object name from the object id
498                   ** first try and find it in the local database
499                   ** if it is not there then it may be a system
500                   ** stored procedure so we need to check in
501                   ** sybsystemprocs..sysobjects (note that we
502                   ** limit the search in this case to sprocs)
503                   */
504                   select @obj_name = user_name(uid) + "." + name
505                   from sysobjects where id = @bnd_obj
506                   if (@obj_name is NULL)
507                   begin
508                       /*
509                       ** the object may be a system stored proc so we
510                       ** need to check sybsystemprocs..sysobjects as
511                       ** well (we can however narrow the search there
512                       ** to only look for procs)
513                       */
514                       select @obj_name = name from
515                           sybsystemprocs..sysobjects
516                       where id = @bnd_obj
517                           and type = 'P'
518   
519                       /*
520                       ** if there is still no object name we have
521                       ** to raise an error
522                       */
523                       if (@obj_name is NULL)
524                       begin
525                           raiserror 19805
526                           return 1
527                       end
528                   end
529   
530                   /*
531                   ** get the path name
532                   */
533                   select @lpath_name = char_value from sysattributes
534                   where class = @MRP_CLASS
535                       and attribute = 22
536                       and object_info1 = @lpath_id
537   
538                   if (@lpath_name is NULL)
539                   begin
540                       /*
541                       ** 19805
542                       ** An unexpected syntax error has occured.
543                       */
544                       raiserror 19805
545                       return 1
546                   end
547                   insert #paths_for_bindings values (@obj_name,
548                       @atype,
549                       @lpath_name)
550               end
551   
552               /*
553               ** Display the bindings and clean up the table
554               */
555               exec sp_autoformat @fulltabname = #paths_for_bindings,
556                   @selectlist = "Binding,Type,Path",
557                   @orderby = "order by Binding,Path"
558   
559               drop table #paths_for_bindings
560   
561               /*
562               ** clean up the cursor
563               */
564               close binding_for_obj_id_cur
565               deallocate binding_for_obj_id_cur
566           end
567   
568           /* 
569           ** if the search_axis is 'all' put a blank line between bindings
570           ** and paths
571           */
572           if (@search_axis = "all")
573           begin
574               print
575           end
576   
577           /*
578           ** if this is a "path" axis search we want to list the objects 
579           ** bound to each path
580           */
581           if (@search_axis = "path")
582           begin
583               /*
584               ** search for all paths in sysattributes 
585               */
586               declare l1_cursor cursor
587               for select object_info1, char_value from sysattributes
588               where class = @MRP_CLASS and attribute = 22
589                   and char_value like @search_name
590               for read only
591   
592               create table #bindings_for_paths(Path varchar(255), Type char(2), Binding varchar(255))
593   
594               open l1_cursor
595   
596               while (1 = 1)
597               begin
598                   fetch l1_cursor into @lpath_id, @lpath_name
599   
600                   if (@@sqlstatus != 0)
601                   begin
602                       break
603                   end
604   
605                   declare l2_cursor cursor
606                   for select object, object_type from sysattributes
607                   where class = @MRP_CLASS and attribute = 23
608                       and object_info1 = @lpath_id
609                   for read only
610   
611                   open l2_cursor
612                   while (1 = 1)
613                   begin
614                       select @obj_name = NULL
615                       fetch l2_cursor into @bnd_obj, @atype
616                       if (@@sqlstatus != 0)
617                       begin
618                           break
619                       end
620   
621                       /*
622                       ** locate the object name from the object id
623                       ** first try and find it in the local database
624                       ** if it is not there then it may be a system
625                       ** stored procedure so we need to check in
626                       ** sybsystemprocs..sysobjects (note that we
627                       ** limit the search in this case to sprocs)
628                       */
629                       select @obj_name = user_name(uid) + "." + name
630                       from sysobjects where id = @bnd_obj
631                       if (@obj_name is NULL)
632                       begin
633                           select @obj_name = name from
634                               sybsystemprocs..sysobjects
635                           where id = @bnd_obj
636                               and type = 'P'
637   
638                           if (@obj_name is NULL)
639                           begin
640                               raiserror 19805
641                               return 1
642                           end
643                       end
644   
645                       insert #bindings_for_paths
646                       values (@lpath_name, @atype, @obj_name)
647                   end
648                   close l2_cursor
649                   deallocate l2_cursor
650               end
651               exec sp_autoformat @fulltabname = #bindings_for_paths,
652                   @selectlist = "Path,Type,Binding",
653                   @orderby = "order by Path,Binding"
654   
655               drop table #bindings_for_paths
656   
657               close l1_cursor
658               deallocate l1_cursor
659           end
660   
661           /*
662           ** 
663           */
664           if (@search_axis = "path" OR @search_axis = "all")
665           begin
666               declare @ppath_elem int
667               /*
668               ** cursor to retrieve logical path ids
669               ** this cursor picks up both strict logical and 
670               ** physical logical path ids, they are handled 
671               ** separately in the while loop
672               */
673               declare lpath_id_curs cursor
674               for select object_info1, char_value from sysattributes
675               where class = @MRP_CLASS and attribute = 22
676                   and char_value like @search_name
677               for read only
678   
679               /*
680               ** create temp tables for logical -> physical paths 
681               ** and physical path -> RS destinations
682               */
683               create table #dest_for_ppath(ppath varchar(255),
684                   dest varchar(255))
685               create table #ppaths_for_lpaths(lpath varchar(255),
686                   ppath varchar(255))
687   
688               open lpath_id_curs
689               while (1 = 1)
690               begin
691                   fetch lpath_id_curs into @lpath_id, @lpath_name
692                   if (@@sqlstatus != 0)
693                   begin
694                       break
695                   end
696   
697                   /*
698                   ** handle strict logical paths
699                   */
700                   if ((select int_value from sysattributes
701                               where class = @MRP_CLASS and attribute = 21
702                                   and object_info1 = @lpath_id) = 1)
703                   begin
704                       /*
705                       ** cursor to get the set of physical path
706                       ** elements contained in this logical path
707                       ** (we need a cursor because there may be
708                       ** multiple physical paths)
709                       */
710                       declare pelem_for_lpath cursor
711                       for select object_info2 from sysattributes
712                       where class = @MRP_CLASS and attribute = 20
713                           and object_info1 = @lpath_id
714   
715                       open pelem_for_lpath
716                       while (1 = 1)
717                       begin
718                           fetch pelem_for_lpath into @ppath_elem
719                           if (@@sqlstatus != 0)
720                           begin
721                               break
722                           end
723   
724                           /*
725                           ** cursor to get the path id for the
726                           ** physical logical path that owns this
727                           ** path element (the path element may
728                           ** be in multiple logical paths)
729                           */
730                           declare pp_id_for_ppath_elem cursor
731                           for select object_info1 from sysattributes
732                           where class = @MRP_CLASS and attribute = 20
733                               and object_info2 = @ppath_elem
734   
735                           open pp_id_for_ppath_elem
736                           while (1 = 1)
737                           begin
738                               fetch pp_id_for_ppath_elem into @ppath_id
739                               if (@@sqlstatus != 0)
740                               begin
741                                   break
742                               end
743   
744                               if ((select int_value from sysattributes
745                                           where class = @MRP_CLASS and attribute = 21
746                                               and object_info1 = @ppath_id) != 0)
747                               begin
748                                   /*
749                                   ** skip strict logical paths
750                                   */
751                                   continue
752                               end
753                               select @ppath_name = char_value
754                               from sysattributes
755                               where class = @MRP_CLASS
756                                   and attribute = 22
757                                   and object_info1 = @ppath_id
758   
759                               insert #ppaths_for_lpaths
760                               values (@lpath_name,
761                                   @ppath_name)
762                               /*
763                               ** if the physical path is not
764                               ** already in the path->dest 
765                               ** table get the RS name for
766                               ** the physical path
767                               */
768                               if ((select count(*) from #dest_for_ppath
769                                           where ppath = @ppath_name) = 0)
770                               begin
771                                   /*
772                                   ** get the name of the 
773                                   ** RepServer for this  
774                                   ** physical path
775                                   */
776                                   select @rs_name = char_value
777                                   from sysattributes
778                                   where class = 11
779                                       and attribute = 0
780                                       and object_info1
781                                       = (select object_info2
782                                           from sysattributes
783                                           where class = @MRP_CLASS
784                                               and attribute = 0
785                                               and object_info1 =
786                                                   (select object_info2
787                                                   from sysattributes
788                                                   where class = @MRP_CLASS
789                                                       and attribute = 20
790                                                       and object_info1 = @ppath_id))
791   
792                                   insert #dest_for_ppath
793                                   values (@ppath_name,
794                                       @rs_name)
795                               end
796                               break
797                           end
798                           close pp_id_for_ppath_elem
799                           deallocate pp_id_for_ppath_elem
800                       end
801                       close pelem_for_lpath
802                       deallocate pelem_for_lpath
803                   end
804                   else
805                   begin
806                       /*
807                       ** if the path name already exists in the 
808                       ** table we can just skip it (this may occur
809                       ** if we have already populated the table 
810                       ** with elements of logical paths)
811                       */
812                       if ((select count(*) from #dest_for_ppath
813                                   where ppath = @lpath_name) > 0)
814                       begin
815                           continue
816                       end
817   
818                       /*
819                       ** get the name of the RepServer for this  
820                       ** physical path
821                       */
822                       select @rs_name = char_value from sysattributes
823                       where class = 11
824                           and attribute = 0
825                           and object_info1 =
826                               (select object_info2
827                               from sysattributes
828                               where class = @MRP_CLASS
829                                   and attribute = 0
830                                   and object_info1 =
831                                       (select object_info2 from
832                                           sysattributes
833                                       where class = @MRP_CLASS
834                                           and attribute = 20
835                                           and object_info1 = @lpath_id))
836   
837                       insert #dest_for_ppath values (@lpath_name,
838                           @rs_name)
839   
840                   end
841               end
842               close lpath_id_curs
843               deallocate lpath_id_curs
844   
845               if ((select count(*) from #ppaths_for_lpaths) > 0)
846               begin
847                   exec sp_autoformat @fulltabname = #ppaths_for_lpaths,
848                       @selectlist = "'Logical Path'=lpath,
849   					'Physical Path'=ppath",
850                       @orderby = "order by lpath"
851               end
852   
853               exec sp_autoformat @fulltabname = #dest_for_ppath,
854                   @selectlist = "'Physical Path'=ppath,'Destination'=dest",
855                   @orderby = "order by ppath"
856   
857               drop table #ppaths_for_lpaths
858               drop table #dest_for_ppath
859           end
860           select @retval = 0
861           goto done
862       end /* action = 'list' */
863   
864       /*
865       ** All actions other than 'list' go through the replication path builtin.
866       ** We will do some simple parameter checking here (basically ensuring that
867       ** the count for each action is reasonable) before passing on to the builtin.
868       */
869       select @retval = 1 /* set default return value to 1 */
870   
871       if (@action = 'add')
872       begin
873           /*
874           ** Add a path (physical or logical) definition to the MRP system.
875           ** There are two distinct syntaxes depending on whether a physical
876           ** or logical path is being added. 
877           ** 
878           **  Var.          physical        logical
879           ** ------------  --------------  ---------------------------
880           **  @p1          avatar name     'logical' keyword modifier
881           **  @p2          rs servername   logical path name
882           **  @p3          rs_username     avatar name
883           **  @p4          rs_password     
884           **  @rs_encpwd   encrypted pwd   
885           ** 
886           ** Errors raised by 'add'
887           **
888           **	error	 description
889           **	-----	-------------------------------------------------------
890           **	18481	'%1!' is an invalid configuration parameter.
891           **	19384	The '%1!' parameter is required with '%2!' parameter.
892           **	19415	The '%1!' parameter is required for the '%2!' command.
893           */
894           if (@p1 = 'logical')
895           begin
896               /*
897               ** 'add', 'logical' requires 2 additional positional parameters
898               */
899               if (@p2 is NULL)
900               begin
901                   raiserror 19384, 'path name', 'logical'
902                   goto done
903               end
904               if (@p3 is NULL)
905               begin
906                   raiserror 19384, 'avatar name', 'logical'
907                   goto done
908               end
909               if (@p4 is not NULL)
910               begin
911                   raiserror 18481, @p4
912                   goto done
913               end
914               if (@rs_encpwd is not NULL)
915               begin
916                   raiserror 18481, @rs_encpwd
917                   goto usage
918               end
919               select @report = "Path '" + @p3 + "' added to logical path '" + @p2 + "'."
920           end
921           else
922           begin
923               /* 
924               ** 'add' for physical requires all 4 positional parameters
925               ** except for @p4 which may be null provided that 
926               ** @rs_encpwd is not null.
927               */
928               if (@p1 is NULL)
929               begin
930                   raiserror 19415, 'Path Name', @action
931                   goto done
932               end
933               if (@p2 is NULL)
934               begin
935                   raiserror 19415, 'RepServer name', @action
936                   goto done
937               end
938               if (@p3 is NULL)
939               begin
940                   raiserror 19415, 'RepServer user name', @action
941                   goto done
942               end
943               if ((@p4 is NULL) and (@rs_encpwd is NULL))
944               begin
945                   raiserror 19415, 'RepServer password', @action
946                   goto done
947               end
948               if ((@p4 is not NULL) and (@rs_encpwd is not NULL))
949               begin
950                   raiserror 18481, @rs_encpwd
951                   goto usage
952               end
953               select @report = "Path '" + @p1 + "' added."
954   
955               if (@rs_encpwd is NULL)
956               begin
957                   /*
958                   ** The rs password (@p4) needs to be encrypted.
959                   */
960                   select @rs_encpwd = internal_encrypt(@p4,
961                           @STATIC_KEY, 0)
962                   if (@rs_encpwd is NULL)
963                   begin
964                       /*
965                       ** 17067 "Unable to encrypt password for '%1!'.
966                       ** See prior error message for reason."
967                       */
968                       raiserror 17067, @dbname
969                   end
970                   select @p4 = NULL
971               end
972   
973               select @status = replication_path_admin(@dbid, @action,
974                       @p1, @p2, @p3,
975                       @rs_encpwd)
976               if (@status != 1)
977               begin
978                   raiserror 18409, "replication_path_admin"
979                   goto done
980               end
981               goto logtran
982           end
983       end
984       else if (@action = 'drop')
985       begin
986           /*
987           ** Drop a path from the MRP environment. Similar to 'add', the 'drop'
988           ** action has both physical and logical syntax
989           **
990           **  Var.   drop (physical)	 drop logical
991           ** -----  --------------------- ---------------------------
992           **  @p1	  avatar (path name)	logical
993           **  @p2   		logical path name
994           **  @p3   		avatar (optional)
995           **  @p4   		
996           **
997           ** Errors with 'drop' action
998           **	error	description
999           **	-----	-------------------------------------------------------
1000          **	19384	The '%1!' parameter is required with '%2!' parameter.
1001          **	19415	The '%1!' parameter is required for the '%2!' command.
1002          **	19805	An unexpected syntax error has occured.	
1003          */
1004          if (@p1 is NULL)
1005          begin
1006              raiserror 11220
1007              goto done
1008          end
1009          else
1010          begin
1011              if (@p1 = 'logical')
1012              begin
1013                  if (@p2 is NULL)
1014                  begin
1015                      raiserror 19384, "path name", "logical"
1016                      goto done
1017                  end
1018                  if ((@p4 is NOT NULL) or (@rs_encpwd is not NULL))
1019                  begin
1020                      /*
1021                      ** 19805
1022                      ** An unexpected syntax error has occured.
1023                      */
1024                      raiserror 19805
1025                      goto done
1026                  end
1027                  if (@p3 is NULL)
1028                  begin
1029                      select @report = "Logical path '" + @p2 +
1030                          "' dropped."
1031                  end
1032                  else
1033                  begin
1034                      select @report = "Path '" + @p3 +
1035                          "' dropped from logical path '" +
1036                          @p2 + "'."
1037                  end
1038              end
1039              else
1040              begin
1041                  if (@p1 is NULL)
1042                  begin
1043                      raiserror 19415, "path name", @action
1044                      goto done
1045                  end
1046                  if (@p2 is not NULL or /* shouldn't be other parameters */
1047                          @p3 is not NULL or
1048                          @p4 is not NULL or
1049                          @rs_encpwd is not NULL)
1050                  begin
1051                      /*
1052                      ** 19805
1053                      ** An unexpected syntax error has occured.
1054                      */
1055                      raiserror 19805
1056                      goto done
1057                  end
1058                  select @report = "Path '" + @p1 + "' dropped."
1059              end
1060          end
1061      end
1062      else if (@action = 'config')
1063      begin
1064          /* 
1065          ** Update or display the value for a given configuration property. 
1066          ** Note that most of the low level config settings for rep agent are
1067          ** set through sp_config_rep_agent, but there are a couple properties
1068          ** that either must be accessible via the sp_replication_path interface
1069          ** or are path specific which are supported through this interface. 
1070          **
1071          **  Var.          config
1072          ** ------------  -----------------------------
1073          **  @p1          physical path name (optional)
1074          **  @p2          config name  (optional)
1075          **  @p3          config value (optional)
1076          **  @p4          
1077          **  @rs_encpwd   encrypted password
1078          **
1079          ** Errors in config
1080          **	error	description
1081          **	-----	-------------------------------------------------------
1082          **	19415	The '%1!' parameter is required for the '%2!' command.
1083          **	19805	An unexpected syntax error has occured.
1084          */
1085  
1086          /*
1087          ** @p4 is never valid
1088          */
1089          if (@p4 is NOT NULL)
1090          begin
1091              /*
1092              ** 19805
1093              ** An unexpected syntax error has occured.
1094              */
1095              raiserror 19805
1096              goto done
1097          end
1098  
1099          /*
1100          ** if @p3 and @rs_encpwd are NULL we are going to display config values 
1101          ** rather than change/set them
1102          */
1103          if ((@p3 is NULL) and (@rs_encpwd is NULL))
1104          begin
1105              declare @path_qual varchar(255) /* path name to search on    */
1106              declare @path_name varchar(255) /* matching path name        */
1107              declare @path_id int /* path id for matching path */
1108  
1109              if (@p1 is NOT NULL)
1110              begin
1111                  select @path_qual = @p1
1112              end
1113              else
1114              begin
1115                  select @path_qual = '%'
1116              end
1117  
1118              /*
1119              ** declare a cursor to get all paths matching the given
1120              ** name (if provided)
1121              */
1122              declare lpath_id_curs cursor
1123              for select object_info1, char_value from sysattributes
1124              where class = @MRP_CLASS and attribute = 22
1125                  and char_value like @path_qual
1126              for read only
1127  
1128              /*
1129              ** create a temp table to hold the config information
1130              ** for the path
1131              ** WARNING: data is written to this table by the builtin
1132              ** do NOT change the layout of this table without also
1133              ** updating the insert statement in the builtin as well
1134              */
1135              create table #config_for_path
1136              (ppath varchar(255) not null,
1137                  rsname varchar(30) not null,
1138                  cfg_name varchar(30) not null,
1139                  cfg_dft varchar(255) default "n/a",
1140                  cfg_cfg varchar(255) default "n/a",
1141                  cfg_run varchar(255) default "n/a")
1142  
1143              open lpath_id_curs
1144              while (1 = 1)
1145              begin
1146                  fetch lpath_id_curs into @path_id, @path_name
1147                  if (@@sqlstatus != 0)
1148                  begin
1149                      break
1150                  end
1151                  if ((select int_value from sysattributes
1152                              where class = @MRP_CLASS and attribute = 21
1153                                  and object_info1 = @path_id) = 0)
1154                  begin
1155                      /*
1156                      ** call the builtin to get the config info
1157                      ** for the next path the cursor retrieved
1158                      ** note that we don't care here if the @p2
1159                      ** is NULL or not, the builtin will check 
1160                      ** if we are looking for a specific config
1161                      ** parameter (i.e. not NULL) but it is
1162                      ** immaterial here
1163                      */
1164                      select @status =
1165                          replication_path_admin(@dbid,
1166                              @action,
1167                              @path_name,
1168                              @p2,
1169                              @p3,
1170                              @p4)
1171                  end
1172              end
1173              exec sp_autoformat
1174                  @fulltabname = "#config_for_path",
1175                  @selectlist = "'Path'=ppath,
1176  				'Rep Server'=rsname,
1177  				'Parameter Name'=cfg_name,
1178  				'Default Value'=cfg_dft,
1179  				'Config Value'=cfg_cfg,
1180  				'Run Value'=cfg_run",
1181                  @orderby = "order by cfg_name"
1182              drop table #config_for_path
1183              return (0)
1184          end
1185          else /* @p3 is not NULL or @rs_encpwd is not NULL */
1186          begin
1187              /*
1188              ** if we get here then we are going to change/set a config
1189              ** value - in this case the path name and config name are
1190              ** not optional, we must have them to proceed
1191              */
1192              if (@p1 is NULL)
1193              begin
1194                  raiserror 19415, 'path name', @action
1195                  goto done
1196              end
1197              if (@p2 is NULL)
1198              begin
1199                  raiserror 19415, 'config name', @action
1200              end
1201              if ((@p3 is not NULL) and (@rs_encpwd is not NULL))
1202              begin
1203                  /*
1204                  ** 19805
1205                  ** An unexpected syntax error has occured.
1206                  */
1207                  raiserror 19805
1208                  goto usage
1209              end
1210  
1211              if (@p2 = 'rs password')
1212              begin
1213                  if (@rs_encpwd is NULL)
1214                  begin
1215                      /*
1216                      ** The rs password (@p3) needs to be encrypted.
1217                      */
1218                      select @rs_encpwd = internal_encrypt(@p3,
1219                              @STATIC_KEY, 0)
1220                      if (@rs_encpwd is NULL)
1221                      begin
1222                          /*
1223                          ** 17067 "Unable to encrypt password 
1224                          ** for '%1!'.
1225                          ** See prior error message for reason."
1226                          */
1227                          raiserror 17067, @dbname
1228                      end
1229                      select @p3 = NULL
1230                  end
1231  
1232                  select @status = replication_path_admin(@dbid, @action,
1233                          @p1, @p2,
1234                          @rs_encpwd,
1235                          @p4)
1236                  if (@status != 1)
1237                  begin
1238                      raiserror 18409, "replication_path_admin"
1239                      goto done
1240                  end
1241                  goto logtran
1242              end
1243          end
1244      end
1245      else if ((@action = 'bind') or (@action = 'unbind'))
1246      begin
1247          /*
1248          ** Create or remove an association between an object and a path. 
1249          ** 
1250          **  Var.          bind	               unbind
1251          ** ------------  ------------------  ---------------
1252          **  @p1          object type         object type
1253          **  @p2          object              object
1254          **  @p3          Log. Path           Log. Path|'all'|""
1255          **  @p4                      
1256          **  @rs_encpwd               
1257          **
1258          ** The object type must be one of the supported types, currently 
1259          ** one of: table|sproc
1260          **
1261          ** For bind all 3 parameters are mandatory. For unbind, the @p3 may
1262          ** be omitted.
1263          **
1264          **	error	description
1265          **	-----	-------------------------------------------------------
1266          **	19415	The '%1!' parameter is required for the '%2!' command.
1267          **	19805	An unexpected syntax error has occured.
1268          */
1269  
1270          /*
1271          ** parts for sp_namecrack on passed in object name 
1272          */
1273          declare @long_name varchar(1023)
1274          declare @site_part varchar(255)
1275          declare @db_part varchar(255)
1276          declare @owner_part varchar(255)
1277          declare @name_part varchar(255)
1278  
1279          declare @sysobj_type varchar(2)
1280  
1281          declare @obj_name_match varchar(255)
1282          declare @usr_name_match varchar(255)
1283  
1284          declare @num_matches int
1285  
1286          declare @curr_path int
1287          declare @curr_user_id int
1288          declare @curr_obj_id int
1289          declare @curr_user_name varchar(255)
1290          declare @curr_obj_name varchar(255)
1291          declare @qualified_name varchar(511)
1292  
1293          declare @is_bound int
1294          declare @issystemproc int
1295  
1296          select @issystemproc = 0
1297  
1298          /*
1299          ** Define the set of supported types that can be bound/unbound
1300          ** Note that we need to add the "path" type for 'unbind'
1301          */
1302          create table #supported_types(obj_type varchar(32) not null unique)
1303          insert #supported_types values ("table")
1304          insert #supported_types values ("sproc")
1305  
1306          if (@action = "unbind")
1307          begin
1308              insert #supported_types values ("path")
1309          end
1310  
1311          /*
1312          ** Both bind and unbind  require the first two parameters
1313          */
1314          if (@p1 is NULL)
1315          begin
1316              raiserror 19415, 'object type', @action
1317              goto done
1318          end
1319          else
1320          begin
1321              /*
1322              ** Check that the object type being bound is a 
1323              ** supported type
1324              */
1325              if ((select count(*) from #supported_types where obj_type = @p1) != 1)
1326              begin
1327                  /*
1328                  ** if the type is a path and the object name is not 'all'
1329                  ** or the object type is any other unsupported type raise
1330                  ** the error
1331                  */
1332                  if (@p1 = 'path' and @p3 != 'all')
1333                  begin
1334                      raiserror 19530, @p1, @action, 'help'
1335                      goto done
1336                  end
1337              end
1338          end
1339  
1340          if (@p2 is NULL)
1341          begin
1342              raiserror 19415, 'object name', @action
1343              goto done
1344          end
1345  
1346          /*
1347          ** 'bind' always requires @p3
1348          */
1349          if (@p3 is NULL)
1350          begin
1351              raiserror 19415, 'path name', @action
1352              goto done
1353          end
1354  
1355          /*
1356          ** @p4 and @rs_encpwd are never used by bind/unbind
1357          */
1358          if ((@p4 is NOT NULL) or (@rs_encpwd is not NULL))
1359          begin
1360              /*
1361              ** 19805
1362              ** An unexpected syntax error has occured.
1363              */
1364              raiserror 19805
1365              goto done
1366          end
1367  
1368  
1369          /*
1370          ** get the pieces of the long name
1371          */
1372          select @long_name = @p2
1373          exec sp_namecrack @long_name,
1374              @site_part output,
1375              @db_part output,
1376              @owner_part output,
1377              @name_part output
1378  
1379          /* 
1380          ** Check if we are attempting to bind a system stored proc.
1381          */
1382          if ((@db_part = "sybsystemprocs" or @db_part = "master")
1383                  and substring(@name_part, 1, 3) = "sp_"
1384                  and user_id(@owner_part) = 1)
1385          begin
1386              select @issystemproc = 1
1387          end
1388  
1389          /*
1390          ** We do allow to bind system stored procedure. Any other object must be
1391          ** in the current database.
1392          */
1393          if (@db_part is NOT NULL and @db_part != db_name() and @issystemproc = 0)
1394          begin
1395              /*
1396              ** 17460, "Object must be in the current database."
1397              */
1398              raiserror 17460
1399              goto done
1400          end
1401  
1402          /*
1403          ** if the object is a table or an sproc and there is a wildcard
1404          ** character ('%' or '*') in the object name then we need special
1405          ** handling
1406          */
1407          if ((@p1 in ('table', 'sproc')) AND
1408                  ((charindex('%', @p2) > 0) OR (charindex('*', @p2) > 0)))
1409          begin
1410              select @num_matches = 0
1411  
1412              /*
1413              ** get the path id from the path name
1414              */
1415              select @curr_path = object_info1 from sysattributes where
1416                  class = @MRP_CLASS and attribute = 22 and char_value = @p3
1417              if (@p3 is NULL or @curr_path is NULL or (@curr_path < 1))
1418              begin
1419                  if (@action != 'unbind' or @p3 != 'all')
1420                  begin
1421                      /*
1422                      ** The '%1!' parameter is required for the '%2!' command.
1423                      */
1424                      raiserror 19415, 'path name', @action
1425                      goto done
1426                  end
1427              end
1428  
1429              /*
1430              ** change '*' all wildcard character to '%' for our search
1431              */
1432              while (charindex('*', @long_name) > 0)
1433              begin
1434                  select @long_name =
1435                      stuff(@long_name,
1436                          charindex('*', @long_name),
1437                          1, '%')
1438              end
1439  
1440              if (@owner_part is NULL)
1441              begin
1442                  select @owner_part = "dbo"
1443              end
1444  
1445  
1446              if (@p1 = "table")
1447              begin
1448                  select @sysobj_type = "U"
1449              end
1450              else
1451              begin
1452                  select @sysobj_type = "P"
1453              end
1454  
1455              /*
1456              ** outer cursor gets the uids for all user
1457              ** name like the passed in owner_part
1458              */
1459              declare currdb_matching_uids cursor
1460              for select uid, name from sysusers where
1461                  name like @owner_part
1462  
1463              /*
1464              ** main inner cursor gets the object names for all
1465              ** objects of the required type, owned by the
1466              ** given user, where the name is like the passed
1467              ** in name_part
1468              */
1469              declare currdb_matching_objects cursor
1470              for select id, name from sysobjects where
1471                  type = @sysobj_type and
1472                  uid = @curr_user_id and
1473                  name like @name_part
1474  
1475              /*
1476              ** the alternate inner cursor gets the object names for all
1477              ** system procs where the name is like the passed in name_part
1478              ** for the system procs we can also check the sysstat to make
1479              ** sure that the sproc is replicable (i.e. O_REPLICATED and
1480              ** O_PROC_SUBSCRIBABLE are set and O2_REP_LOG_SPROC is not)
1481              ** note that the additional checks on sysstat and sysstat2 are
1482              ** not enforced in the non-wildcard bind/unbind because the 
1483              ** built-in will report a meaningful error; in the wildcard 
1484              ** case a poorly chosen search could generate thousands of
1485              ** lines of error messages
1486              */
1487              declare sybsystemprocs_matching_sprocs cursor
1488              for select id, name from sybsystemprocs..sysobjects where
1489                  type = "P" and uid = 1 and
1490                  ((sysstat & 64) = 64) and
1491                  ((sysstat & 32768) = 32768) and
1492                  ((sysstat2 & 8388608) = 0) and
1493                  name like @name_part
1494  
1495              /*
1496              ** open the outer cursor and process through 
1497              ** matching uids
1498              */
1499              open currdb_matching_uids
1500              while (1 = 1)
1501              begin
1502                  fetch currdb_matching_uids into
1503                      @curr_user_id, @curr_user_name
1504                  if (@@sqlstatus != 0)
1505                  begin
1506                      break
1507                  end
1508  
1509                  /*
1510                  ** open the main inner cursor and process
1511                  ** through matching object names
1512                  */
1513                  open currdb_matching_objects
1514                  while (1 = 1)
1515                  begin
1516                      fetch currdb_matching_objects into
1517                          @curr_obj_id, @curr_obj_name
1518                      if (@@sqlstatus != 0)
1519                      begin
1520                          break
1521                      end
1522  
1523                      select @qualified_name =
1524                          @curr_user_name + "." + @curr_obj_name
1525  
1526                      if (@p3 != 'all')
1527                      begin
1528                          /*
1529                          ** get the number of bindings that match 
1530                          ** the search criterion
1531                          */
1532                          select @is_bound = count(*) from sysattributes
1533                          where class = @MRP_CLASS and
1534                              attribute = 23 and
1535                              object_info1 = @curr_path and
1536                              object = @curr_obj_id
1537  
1538                          /*
1539                          ** sanity check, we should never have more
1540                          ** than one match
1541                          */
1542                          if (@is_bound > 1)
1543                          begin
1544                              raiserror 19908, @qualified_name
1545                              goto done
1546                          end
1547                      end
1548  
1549                      /*
1550                      ** there are two cases that we check for with
1551                      ** wildcards:
1552                      ** - if action is bind and the object is
1553                      **   already bound
1554                      ** - id action is unbind and the object is
1555                      **   not currently bound
1556                      ** in both cases the state of the object is
1557                      ** unchanged so the object is silently skipped
1558                      ** (this is a bit different that the explicit
1559                      **  case where the builtin warns the user that
1560                      **  the object is already in the desired state)
1561                      */
1562                      if (((@action = 'bind') and (@is_bound = 1)) or
1563                              ((@action = 'unbind') and (@is_bound = 0)))
1564                      begin
1565                          continue
1566                      end
1567  
1568                      select @status =
1569                          replication_path_admin(@dbid,
1570                              @action,
1571                              @p1,
1572                              @qualified_name,
1573                              @p3,
1574                              @p4)
1575                      if (@status != 1)
1576                      begin
1577                          raiserror 18409, "replication_path_admin"
1578                      end
1579                      select @num_matches = @num_matches + 1
1580                  end
1581                  /*
1582                  ** close the (inner) current database objects cursor
1583                  */
1584                  close currdb_matching_objects
1585  
1586                  /*
1587                  ** if the object type is an sproc and this is the dbo
1588                  ** user then we need to check if the name_part is
1589                  ** referring to a system stored proc
1590                  */
1591                  if (@sysobj_type = "P" and @curr_user_id = 1)
1592                  begin
1593                      open sybsystemprocs_matching_sprocs
1594                      while (1 = 1)
1595                      begin
1596                          select @curr_obj_id = 0
1597                          select @curr_obj_name = NULL
1598                          fetch sybsystemprocs_matching_sprocs
1599                          into @curr_obj_id,
1600                              @curr_obj_name
1601                          if (@@sqlstatus != 0)
1602                          begin
1603                              break
1604                          end
1605  
1606                          /*
1607                          ** if the path name is not 'all' get
1608                          ** the number of bindings that match 
1609                          ** the search criterion
1610                          */
1611                          if (@p3 != 'all')
1612                          begin
1613                              select @is_bound = count(*)
1614                              from sysattributes
1615                              where class = @MRP_CLASS and
1616                                  attribute = 23 and
1617                                  object_info1 = @curr_path and
1618                                  object = @curr_obj_id
1619  
1620                              /*
1621                              ** sanity check, we should never have 
1622                              ** more than one match
1623                              */
1624                              if (@is_bound > 1)
1625                              begin
1626                                  raiserror 19908, @curr_obj_name
1627                                  goto done
1628                              end
1629                          end
1630  
1631                          /*
1632                          ** there are two cases that we check for
1633                          ** with wildcards:
1634                          ** - if action is bind and the object is
1635                          **   already bound
1636                          ** - id action is unbind and the object
1637                          **   is not currently bound
1638                          ** in both cases the state of the object
1639                          ** is unchanged so the object is silently
1640                          ** skipped (this is a bit different that
1641                          ** the explicit case where the builtin
1642                          ** warns the user that the object is 
1643                          ** already in the desired state)
1644                          */
1645                          if (((@action = 'bind') and
1646                                      (@is_bound = 1)) or
1647                                  ((@action = 'unbind') and
1648                                      (@is_bound = 0)))
1649                          begin
1650                              continue
1651                          end
1652  
1653                          select @status =
1654                              replication_path_admin(@dbid,
1655                                  @action,
1656                                  @p1,
1657                                  @curr_obj_name,
1658                                  @p3,
1659                                  @p4)
1660                          if (@status != 1)
1661                          begin
1662                              raiserror 18409,
1663                                  "replication_path_admin"
1664                          end
1665                          select @num_matches = @num_matches + 1
1666                      end
1667                      /*
1668                      ** close the (inner) system sproc cursor
1669                      */
1670                      close sybsystemprocs_matching_sprocs
1671                  end
1672              end
1673              /*
1674              ** close the (outer) uid cursor
1675              */
1676              close currdb_matching_uids
1677  
1678              /*
1679              ** clean up all the cursors
1680              */
1681              deallocate sybsystemprocs_matching_sprocs
1682              deallocate currdb_matching_objects
1683              deallocate currdb_matching_uids
1684  
1685              /*
1686              ** set up the report string
1687              */
1688              if (@action = 'bind')
1689              begin
1690                  select @report = convert(varchar(8), @num_matches) + " "
1691                      + @p1 + "(s) matching '" + @p2
1692                      + "' bound to path '" + @p3 + "'."
1693              end
1694              else /* else action is 'unbind' */
1695              begin
1696                  select @report = convert(varchar(8), @num_matches) + " "
1697                      + @p1 + "(s) matching '" + @p2
1698                      + "' unbound from path '" + @p3 + "'."
1699              end
1700  
1701              /*
1702              ** we have already called the builtin for any matching
1703              ** objects jump to the logging for replication  
1704              */
1705              goto logtran
1706          end
1707          else
1708          begin
1709              if (@action = 'bind')
1710              begin
1711                  select @report = "The " + @p1 + " '" + @p2 +
1712                      "' is bound to path '" + @p3 + "'."
1713              end
1714              else
1715              begin
1716                  select @report = "The " + @p1 + " '" + @p2 +
1717                      "' is unbound from path '" + @p3 + "'."
1718              end
1719          end
1720      end
1721  
1722  call_builtin:
1723      /*
1724      ** if we have not performed the action via wildcard handling
1725      ** we should have a correct parameter count at this point so
1726      ** call the built-in 
1727      */
1728      select @status = replication_path_admin(@dbid, @action,
1729              @p1, @p2, @p3, @p4)
1730      if (@status != 1)
1731      begin
1732          /*
1733          ** if we do not get a successful status we need to check
1734          ** if the status indicates no action was taken; in this
1735          ** case we just clear the status message and go on
1736          */
1737          if (@status = - 1)
1738          begin
1739              select @report = NULL
1740          end
1741          else
1742          begin
1743              raiserror 18409, "replication_path_admin"
1744              goto done
1745          end
1746      end
1747  
1748      /*
1749      ** Write the log records to replicate this invocation of the 
1750      ** stored procedure.
1751      */
1752  logtran:
1753      begin transaction rs_logexec
1754  
1755      if (logexec(@dbid) != 1)
1756      begin
1757          /*
1758          ** 17756, "The execution of the stored procedure '%1!'
1759          **	 in database '%2!' was aborted because there
1760          **	 was an error in writing the replication log
1761          **	 record."
1762          */
1763          raiserror 17756, "sp_replication_path", @dbname
1764          rollback transaction rs_logexec
1765          goto done
1766      end
1767      commit transaction
1768  
1769      /*
1770      ** If we have gotten here then everything has gone as expected,
1771      ** if there is a report (not null) then print it out. The contents
1772      ** of the report are filled out in the individual action section.
1773      */
1774      if (@report is not NULL)
1775      begin
1776          print "%1!", @report
1777      end
1778  
1779      /*
1780      ** if we get here, everything has gone ok - set the retval to 0
1781      ** and jump to the cleanup section
1782      */
1783      select @retval = 0
1784      goto done
1785  
1786      /* end of normal processing */
1787  
1788  usage:
1789      /*
1790      ** never good news if we get here, set the retval to 1
1791      **  and print usage information before we exit
1792      */
1793      select @retval = 1
1794  
1795      print "sp_replication_path Usage:"
1796      print "sp_replication_path <dbname>, 'add', 'Path Name', 'RepServer Name', 'rs username', 'rs password'"
1797      print "sp_replication_path <dbname>, 'add', 'logical', 'Logical Path Name', 'Path Name'"
1798      print "sp_replication_path <dbname>, 'drop', 'Path Name'"
1799      print "sp_replication_path <dbname>, 'drop', 'logical', 'Logical Path Name' [, 'Path Name']"
1800      print "sp_replication_path <dbname>, 'bind', 'table'|'sproc', '[ownername.]objectname', 'Path Name'"
1801      print "sp_replication_path <dbname>, 'unbind', 'table'|'sproc', '[ownername.]objectname', 'Path Name'"
1802      print "sp_replication_path <dbname>, 'unbind', 'path', 'Path Name'"
1803      print "sp_replication_path <dbname>, 'config', 'Path Name' [, 'config name' [, 'config value']]"
1804      print "sp_replication_path <dbname>, 'list'"
1805      print "sp_replication_path <dbname>, 'list', 'all'"
1806      print "sp_replication_path <dbname>, 'list', 'table|sproc'[, '[ownername.]objectname']"
1807      print "sp_replication_path <dbname>, 'list', 'path' [, 'Path Name']"
1808  
1809  done:
1810      return @retval
1811  


exec sp_procxmode 'sp_replication_path', 'AnyMode'
go

Grant Execute on sp_replication_path to public
go
DEFECTS
 MINU 4 Unique Index with nullable columns sybsystemprocs..sysattributes sybsystemprocs..sysattributes
 MTYP 4 Assignment type mismatch @search_name: varchar(255) = varchar(1023) 313
 MTYP 4 Assignment type mismatch @lpath_name: varchar(255) = varchar(768) 533
 MTYP 4 Assignment type mismatch @ppath_name: varchar(255) = varchar(768) 753
 MTYP 4 Assignment type mismatch @rs_name: varchar(255) = varchar(768) 776
 MTYP 4 Assignment type mismatch @rs_name: varchar(255) = varchar(768) 822
 MUSP 4 Unquoted String Parameter sybsystemprocs..sp_autoformat: @fulltabname 555
 MUSP 4 Unquoted String Parameter sybsystemprocs..sp_autoformat: @fulltabname 651
 MUSP 4 Unquoted String Parameter sybsystemprocs..sp_autoformat: @fulltabname 847
 MUSP 4 Unquoted String Parameter sybsystemprocs..sp_autoformat: @fulltabname 853
 QCSC 4 Costly 'select count()', use 'exists()' 419
 QCSC 4 Costly 'select count()', use 'exists()' 432
 QCSC 4 Costly 'select count()', use 'exists()' 768
 QCSC 4 Costly 'select count()', use 'exists()' 812
 QCSC 4 Costly 'select count()', use 'exists()' 845
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 309
 QTYP 4 Comparison type mismatch smallint = int 309
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 310
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 471
 QTYP 4 Comparison type mismatch smallint = int 471
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 534
 QTYP 4 Comparison type mismatch smallint = int 534
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 535
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 588
 QTYP 4 Comparison type mismatch smallint = int 588
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 607
 QTYP 4 Comparison type mismatch smallint = int 607
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 675
 QTYP 4 Comparison type mismatch smallint = int 675
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 701
 QTYP 4 Comparison type mismatch smallint = int 701
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 712
 QTYP 4 Comparison type mismatch smallint = int 712
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 732
 QTYP 4 Comparison type mismatch smallint = int 732
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 745
 QTYP 4 Comparison type mismatch smallint = int 745
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 755
 QTYP 4 Comparison type mismatch smallint = int 755
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 756
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 778
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 779
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 783
 QTYP 4 Comparison type mismatch smallint = int 783
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 784
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 788
 QTYP 4 Comparison type mismatch smallint = int 788
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 789
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 823
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 824
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 828
 QTYP 4 Comparison type mismatch smallint = int 828
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 829
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 833
 QTYP 4 Comparison type mismatch smallint = int 833
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 834
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 1124
 QTYP 4 Comparison type mismatch smallint = int 1124
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 1152
 QTYP 4 Comparison type mismatch smallint = int 1152
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 1416
 QTYP 4 Comparison type mismatch smallint = int 1416
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 1533
 QTYP 4 Comparison type mismatch smallint = int 1533
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 1534
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 1615
 QTYP 4 Comparison type mismatch smallint = int 1615
 QTYP 4 Comparison type mismatch Comparison type mismatch: smallint vs int 1616
 VRUN 4 Variable is read and not initialized @curr_user_id 1472
 CUNU 3 Cursor not updated: cursor should contain 'for read only' clause pp_id_for_ppath_elem 731
 CUNU 3 Cursor not updated: cursor should contain 'for read only' clause currdb_matching_uids 1460
 MGTP 3 Grant to public master..sysdatabases  
 MGTP 3 Grant to public sybsystemprocs..sp_replication_path  
 MGTP 3 Grant to public sybsystemprocs..sysattributes  
 MGTP 3 Grant to public sybsystemprocs..sysobjects  
 MGTP 3 Grant to public sybsystemprocs..sysusers  
 MNER 3 No Error Check should check @@error after insert 547
 MNER 3 No Error Check should check return value of exec 555
 MNER 3 No Error Check should check @@error after insert 645
 MNER 3 No Error Check should check return value of exec 651
 MNER 3 No Error Check should check @@error after insert 759
 MNER 3 No Error Check should check @@error after insert 792
 MNER 3 No Error Check should check @@error after insert 837
 MNER 3 No Error Check should check return value of exec 847
 MNER 3 No Error Check should check return value of exec 853
 MNER 3 No Error Check should check return value of exec 1173
 MNER 3 No Error Check should check @@error after insert 1303
 MNER 3 No Error Check should check @@error after insert 1304
 MNER 3 No Error Check should check @@error after insert 1308
 MNER 3 No Error Check should check return value of exec 1373
 MUCO 3 Useless Code Useless Brackets 80
 MUCO 3 Useless Code Useless Brackets 87
 MUCO 3 Useless Code Useless Brackets 109
 MUCO 3 Useless Code Useless Brackets 115
 MUCO 3 Useless Code Useless Brackets 130
 MUCO 3 Useless Code Useless Brackets 133
 MUCO 3 Useless Code Useless Brackets 146
 MUCO 3 Useless Code Useless Brackets 151
 MUCO 3 Useless Code Useless Brackets 153
 MUCO 3 Useless Code Useless Brackets 160
 MUCO 3 Useless Code Useless Brackets 167
 MUCO 3 Useless Code Useless Brackets 174
 MUCO 3 Useless Code Useless Brackets 177
 MUCO 3 Useless Code Useless Brackets 188
 MUCO 3 Useless Code Useless Brackets 275
 MUCO 3 Useless Code Useless Brackets 288
 MUCO 3 Useless Code Useless Brackets 290
 MUCO 3 Useless Code Useless Brackets 293
 MUCO 3 Useless Code Useless Brackets 303
 MUCO 3 Useless Code Useless Brackets 306
 MUCO 3 Useless Code Useless Brackets 322
 MUCO 3 Useless Code Useless Brackets 340
 MUCO 3 Useless Code Useless Brackets 345
 MUCO 3 Useless Code Useless Brackets 349
 MUCO 3 Useless Code Useless Brackets 363
 MUCO 3 Useless Code Useless Brackets 366
 MUCO 3 Useless Code Useless Brackets 368
 MUCO 3 Useless Code Useless Brackets 377
 MUCO 3 Useless Code Useless Brackets 381
 MUCO 3 Useless Code Useless Brackets 418
 MUCO 3 Useless Code Useless Brackets 429
 MUCO 3 Useless Code Useless Brackets 431
 MUCO 3 Useless Code Useless Brackets 443
 MUCO 3 Useless Code Useless Brackets 462
 MUCO 3 Useless Code Useless Brackets 480
 MUCO 3 Useless Code Useless Brackets 491
 MUCO 3 Useless Code Useless Brackets 506
 MUCO 3 Useless Code Useless Brackets 523
 MUCO 3 Useless Code Useless Brackets 538
 MUCO 3 Useless Code Useless Brackets 572
 MUCO 3 Useless Code Useless Brackets 581
 MUCO 3 Useless Code Useless Brackets 596
 MUCO 3 Useless Code Useless Brackets 600
 MUCO 3 Useless Code Useless Brackets 612
 MUCO 3 Useless Code Useless Brackets 616
 MUCO 3 Useless Code Useless Brackets 631
 MUCO 3 Useless Code Useless Brackets 638
 MUCO 3 Useless Code Useless Brackets 664
 MUCO 3 Useless Code Useless Brackets 689
 MUCO 3 Useless Code Useless Brackets 692
 MUCO 3 Useless Code Useless Brackets 700
 MUCO 3 Useless Code Useless Brackets 716
 MUCO 3 Useless Code Useless Brackets 719
 MUCO 3 Useless Code Useless Brackets 736
 MUCO 3 Useless Code Useless Brackets 739
 MUCO 3 Useless Code Useless Brackets 744
 MUCO 3 Useless Code Useless Brackets 768
 MUCO 3 Useless Code Useless Brackets 812
 MUCO 3 Useless Code Useless Brackets 845
 MUCO 3 Useless Code Useless Brackets 871
 MUCO 3 Useless Code Useless Brackets 894
 MUCO 3 Useless Code Useless Brackets 899
 MUCO 3 Useless Code Useless Brackets 904
 MUCO 3 Useless Code Useless Brackets 909
 MUCO 3 Useless Code Useless Brackets 914
 MUCO 3 Useless Code Useless Brackets 928
 MUCO 3 Useless Code Useless Brackets 933
 MUCO 3 Useless Code Useless Brackets 938
 MUCO 3 Useless Code Useless Brackets 943
 MUCO 3 Useless Code Useless Brackets 948
 MUCO 3 Useless Code Useless Brackets 955
 MUCO 3 Useless Code Useless Brackets 962
 MUCO 3 Useless Code Useless Brackets 976
 MUCO 3 Useless Code Useless Brackets 984
 MUCO 3 Useless Code Useless Brackets 1004
 MUCO 3 Useless Code Useless Brackets 1011
 MUCO 3 Useless Code Useless Brackets 1013
 MUCO 3 Useless Code Useless Brackets 1018
 MUCO 3 Useless Code Useless Brackets 1027
 MUCO 3 Useless Code Useless Brackets 1041
 MUCO 3 Useless Code Useless Brackets 1046
 MUCO 3 Useless Code Useless Brackets 1062
 MUCO 3 Useless Code Useless Brackets 1089
 MUCO 3 Useless Code Useless Brackets 1103
 MUCO 3 Useless Code Useless Brackets 1109
 MUCO 3 Useless Code Useless Brackets 1144
 MUCO 3 Useless Code Useless Brackets 1147
 MUCO 3 Useless Code Useless Brackets 1151
 MUCO 3 Useless Code Useless Brackets 1183
 MUCO 3 Useless Code Useless Brackets 1192
 MUCO 3 Useless Code Useless Brackets 1197
 MUCO 3 Useless Code Useless Brackets 1201
 MUCO 3 Useless Code Useless Brackets 1211
 MUCO 3 Useless Code Useless Brackets 1213
 MUCO 3 Useless Code Useless Brackets 1220
 MUCO 3 Useless Code Useless Brackets 1236
 MUCO 3 Useless Code Useless Brackets 1245
 MUCO 3 Useless Code Useless Brackets 1306
 MUCO 3 Useless Code Useless Brackets 1314
 MUCO 3 Useless Code Useless Brackets 1325
 MUCO 3 Useless Code Useless Brackets 1332
 MUCO 3 Useless Code Useless Brackets 1340
 MUCO 3 Useless Code Useless Brackets 1349
 MUCO 3 Useless Code Useless Brackets 1358
 MUCO 3 Useless Code Useless Brackets 1382
 MUCO 3 Useless Code Useless Brackets 1393
 MUCO 3 Useless Code Useless Brackets 1407
 MUCO 3 Useless Code Useless Brackets 1417
 MUCO 3 Useless Code Useless Brackets 1419
 MUCO 3 Useless Code Useless Brackets 1432
 MUCO 3 Useless Code Useless Brackets 1440
 MUCO 3 Useless Code Useless Brackets 1446
 MUCO 3 Useless Code Useless Brackets 1500
 MUCO 3 Useless Code Useless Brackets 1504
 MUCO 3 Useless Code Useless Brackets 1514
 MUCO 3 Useless Code Useless Brackets 1518
 MUCO 3 Useless Code Useless Brackets 1526
 MUCO 3 Useless Code Useless Brackets 1542
 MUCO 3 Useless Code Useless Brackets 1562
 MUCO 3 Useless Code Useless Brackets 1575
 MUCO 3 Useless Code Useless Brackets 1591
 MUCO 3 Useless Code Useless Brackets 1594
 MUCO 3 Useless Code Useless Brackets 1601
 MUCO 3 Useless Code Useless Brackets 1611
 MUCO 3 Useless Code Useless Brackets 1624
 MUCO 3 Useless Code Useless Brackets 1645
 MUCO 3 Useless Code Useless Brackets 1660
 MUCO 3 Useless Code Useless Brackets 1688
 MUCO 3 Useless Code Useless Brackets 1709
 MUCO 3 Useless Code Useless Brackets 1730
 MUCO 3 Useless Code Useless Brackets 1737
 MUCO 3 Useless Code Useless Brackets 1755
 MUCO 3 Useless Code Useless Brackets 1774
 MUIN 3 Column created using implicit nullability 476
 MUIN 3 Column created using implicit nullability 592
 MUIN 3 Column created using implicit nullability 683
 MUIN 3 Column created using implicit nullability 685
 MUIN 3 Column created using implicit nullability 1135
 QAFM 3 Var Assignment from potentially many rows 533
 QAFM 3 Var Assignment from potentially many rows 753
 QAFM 3 Var Assignment from potentially many rows 776
 QAFM 3 Var Assignment from potentially many rows 822
 QAFM 3 Var Assignment from potentially many rows 1415
 QCTC 3 Conditional Table Creation 476
 QCTC 3 Conditional Table Creation 592
 QCTC 3 Conditional Table Creation 683
 QCTC 3 Conditional Table Creation 685
 QCTC 3 Conditional Table Creation 1135
 QCTC 3 Conditional Table Creation 1302
 QISO 3 Set isolation level 94
 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}
309
 QPRI 3 Join or Sarg with Rooted Partial Index Use SARG Candidate index: sysobjects.ncsysobjects unique
(name, uid)
Intersection: {name}
420
 QPRI 3 Join or Sarg with Rooted Partial Index Use SARG Candidate index: sysobjects.ncsysobjects unique
(name, uid)
Intersection: {name}
433
 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_type, object, attribute, class}
471
 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, object_info1, attribute}
534
 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}
588
 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, object_info1, attribute}
607
 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}
675
 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, object_info1, attribute}
701
 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, object_info1, attribute}
712
 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_info2, class, attribute}
732
 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, object_info1, attribute}
745
 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, object_info1, attribute}
755
 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, object_info1, attribute}
778
 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, object_info1, attribute}
783
 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, object_info1, attribute}
788
 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, object_info1, attribute}
823
 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, object_info1, attribute}
828
 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, object_info1, attribute}
833
 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}
1124
 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, object_info1, attribute}
1152
 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}
1416
 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, attribute, class}
1533
 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, attribute, class}
1615
 VNRD 3 Variable is not read @blt_failure 97
 VNRD 3 Variable is not read @rep_all 98
 VNRD 3 Variable is not read @rep_l1 99
 VNRD 3 Variable is not read @rep_constant 100
 VNRD 3 Variable is not read @site_part 1374
 VUNU 3 Variable is not used @owner 55
 VUNU 3 Variable is not used @db 56
 VUNU 3 Variable is not used @rs_id 256
 VUNU 3 Variable is not used @obj_name_match 1281
 VUNU 3 Variable is not used @usr_name_match 1282
 CRDO 2 Read Only Cursor Marker (has for read only clause) 470
 CRDO 2 Read Only Cursor Marker (has for read only clause) 587
 CRDO 2 Read Only Cursor Marker (has for read only clause) 606
 CRDO 2 Read Only Cursor Marker (has for read only clause) 674
 CRDO 2 Read Only Cursor Marker (has for read only clause) 1123
 CUPD 2 Updatable Cursor Marker (updatable by default) 711
 CUPD 2 Updatable Cursor Marker (updatable by default) 731
 CUPD 2 Updatable Cursor Marker (updatable by default) 1460
 CUPD 2 Updatable Cursor Marker (updatable by default) 1470
 CUPD 2 Updatable Cursor Marker (updatable by default) 1488
 MSUB 2 Subquery Marker 308
 MSUB 2 Subquery Marker 419
 MSUB 2 Subquery Marker 432
 MSUB 2 Subquery Marker 700
 MSUB 2 Subquery Marker 744
 MSUB 2 Subquery Marker 768
 MSUB 2 Subquery Marker 781
 MSUB 2 Subquery Marker 786
 MSUB 2 Subquery Marker 812
 MSUB 2 Subquery Marker 826
 MSUB 2 Subquery Marker 831
 MSUB 2 Subquery Marker 1151
 MSUB 2 Subquery Marker 1325
 MTR1 2 Metrics: Comments Ratio Comments: 45% 31
 MTR2 2 Metrics: Cyclomatic Complexity Cyclo: 212 = 224dec - 14exi + 2 31
 MTR3 2 Metrics: Query Complexity Complexity: 780 31

DEPENDENCIES
PROCS AND TABLES USED
read_writes table tempdb..#supported_types (1) 
writes table tempdb..#paths_for_bindings (1) 
calls proc sybsystemprocs..sp_namecrack  
writes table tempdb..#config_for_path (1) 
reads table sybsystemprocs..sysattributes  
read_writes table tempdb..#ppaths_for_lpaths (1) 
reads table master..sysdatabases (1)  
writes table tempdb..#bindings_for_paths (1) 
reads table sybsystemprocs..sysobjects  
calls proc sybsystemprocs..sp_autoformat  
   reads table tempdb..syscolumns (1)  
   calls proc sybsystemprocs..sp_autoformat  
   reads table master..syscolumns (1)  
   calls proc sybsystemprocs..sp_namecrack  
   reads table master..systypes (1)  
   read_writes table tempdb..#colinfo_af (1) 
   reads table tempdb..systypes (1)  
reads table sybsystemprocs..sysusers  
read_writes table tempdb..#dest_for_ppath (1)